提交测试代码
This commit is contained in:
@@ -1,40 +1,40 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
[CustomEditor(typeof(FloatBobberController))]
|
||||
public class FloatBobberControllerEditor : Editor
|
||||
{
|
||||
private FloatBobberController _target;
|
||||
void OnEnable()
|
||||
{
|
||||
_target = target as FloatBobberController;
|
||||
// lookAtPoint = serializedObject.FindProperty("lookAtPoint");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
if (GUILayout.Button("TriggerDownPulse"))
|
||||
{
|
||||
_target.TriggerDownPulse();
|
||||
}
|
||||
if (GUILayout.Button("TriggerUpPulse"))
|
||||
{
|
||||
_target.TriggerUpPulse();
|
||||
}
|
||||
if (GUILayout.Button("AddFishPull"))
|
||||
{
|
||||
_target.AddFishPull(0.5f);
|
||||
}
|
||||
if (GUILayout.Button("AddFishPull"))
|
||||
{
|
||||
_target.ReleaseFishPull(0.5f);
|
||||
}
|
||||
// serializedObject.Update();
|
||||
// EditorGUILayout.PropertyField(lookAtPoint);
|
||||
// serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
// using UnityEditor;
|
||||
// using UnityEngine;
|
||||
//
|
||||
// namespace NBF
|
||||
// {
|
||||
// [CustomEditor(typeof(FloatBobberController))]
|
||||
// public class FloatBobberControllerEditor : Editor
|
||||
// {
|
||||
// private FloatBobberController _target;
|
||||
// void OnEnable()
|
||||
// {
|
||||
// _target = target as FloatBobberController;
|
||||
// // lookAtPoint = serializedObject.FindProperty("lookAtPoint");
|
||||
// }
|
||||
//
|
||||
// public override void OnInspectorGUI()
|
||||
// {
|
||||
// base.OnInspectorGUI();
|
||||
// if (GUILayout.Button("TriggerDownPulse"))
|
||||
// {
|
||||
// _target.TriggerDownPulse();
|
||||
// }
|
||||
// if (GUILayout.Button("TriggerUpPulse"))
|
||||
// {
|
||||
// _target.TriggerUpPulse();
|
||||
// }
|
||||
// if (GUILayout.Button("AddFishPull"))
|
||||
// {
|
||||
// _target.AddFishPull(0.5f);
|
||||
// }
|
||||
// if (GUILayout.Button("AddFishPull"))
|
||||
// {
|
||||
// _target.ReleaseFishPull(0.5f);
|
||||
// }
|
||||
// // serializedObject.Update();
|
||||
// // EditorGUILayout.PropertyField(lookAtPoint);
|
||||
// // serializedObject.ApplyModifiedProperties();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1,40 +1,40 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
[CustomEditor(typeof(FloatBobberControllerPro))]
|
||||
public class FloatBobberControllerProEditor : Editor
|
||||
{
|
||||
private FloatBobberControllerPro _target;
|
||||
void OnEnable()
|
||||
{
|
||||
_target = target as FloatBobberControllerPro;
|
||||
// lookAtPoint = serializedObject.FindProperty("lookAtPoint");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
if (GUILayout.Button("TriggerDownPulse"))
|
||||
{
|
||||
_target.TriggerDownPulse();
|
||||
}
|
||||
if (GUILayout.Button("TriggerUpPulse"))
|
||||
{
|
||||
_target.TriggerUpPulse();
|
||||
}
|
||||
if (GUILayout.Button("AddFishPull"))
|
||||
{
|
||||
_target.AddFishPull(0.5f);
|
||||
}
|
||||
if (GUILayout.Button("AddFishPull"))
|
||||
{
|
||||
_target.ReleaseFishPull(0.5f);
|
||||
}
|
||||
// serializedObject.Update();
|
||||
// EditorGUILayout.PropertyField(lookAtPoint);
|
||||
// serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
// using UnityEditor;
|
||||
// using UnityEngine;
|
||||
//
|
||||
// namespace NBF
|
||||
// {
|
||||
// [CustomEditor(typeof(FloatBobberControllerPro))]
|
||||
// public class FloatBobberControllerProEditor : Editor
|
||||
// {
|
||||
// private FloatBobberControllerPro _target;
|
||||
// void OnEnable()
|
||||
// {
|
||||
// _target = target as FloatBobberControllerPro;
|
||||
// // lookAtPoint = serializedObject.FindProperty("lookAtPoint");
|
||||
// }
|
||||
//
|
||||
// public override void OnInspectorGUI()
|
||||
// {
|
||||
// base.OnInspectorGUI();
|
||||
// if (GUILayout.Button("TriggerDownPulse"))
|
||||
// {
|
||||
// _target.TriggerDownPulse();
|
||||
// }
|
||||
// if (GUILayout.Button("TriggerUpPulse"))
|
||||
// {
|
||||
// _target.TriggerUpPulse();
|
||||
// }
|
||||
// if (GUILayout.Button("AddFishPull"))
|
||||
// {
|
||||
// _target.AddFishPull(0.5f);
|
||||
// }
|
||||
// if (GUILayout.Button("AddFishPull"))
|
||||
// {
|
||||
// _target.ReleaseFishPull(0.5f);
|
||||
// }
|
||||
// // serializedObject.Update();
|
||||
// // EditorGUILayout.PropertyField(lookAtPoint);
|
||||
// // serializedObject.ApplyModifiedProperties();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -17,7 +17,7 @@ namespace NBF
|
||||
[SerializeField] private Rope bobberRope;
|
||||
public LureController Lure;
|
||||
public BobberController Bobber;
|
||||
|
||||
|
||||
|
||||
private float _groundSetting = 0.5f;
|
||||
|
||||
@@ -32,7 +32,6 @@ namespace NBF
|
||||
protected override void OnInit()
|
||||
{
|
||||
var tipRb = Rod.Asset.LineConnectorRigidbody;
|
||||
// startParticleAttachment.target = tipRb.transform;
|
||||
if (isLureConnect)
|
||||
{
|
||||
Lure.SetJoint(tipRb);
|
||||
@@ -48,7 +47,6 @@ namespace NBF
|
||||
Lure.SetKinematic(false);
|
||||
}
|
||||
|
||||
// onLureInit.Raise(lure.gameObject);
|
||||
GetComponentsInChildren<Transform>(includeInactive: true).ToList().ForEach(delegate(Transform i)
|
||||
{
|
||||
i.gameObject.SetActive(true);
|
||||
@@ -68,6 +66,40 @@ namespace NBF
|
||||
// rodLine.GenerateLineRendererRope(guides.ToArray(), _LineThickness);
|
||||
}
|
||||
|
||||
public void InitTest(Rigidbody tipRb)
|
||||
{
|
||||
if (isLureConnect)
|
||||
{
|
||||
Lure.SetJoint(tipRb);
|
||||
Lure.EnableCollision(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
fishingRope.startAnchor = tipRb;
|
||||
Bobber.SetJoint(tipRb);
|
||||
Lure.SetJoint(Bobber.rbody);
|
||||
Lure.gameObject.SetActive(true);
|
||||
Lure.EnableCollision(false);
|
||||
Lure.SetKinematic(false);
|
||||
}
|
||||
|
||||
GetComponentsInChildren<Transform>(includeInactive: true).ToList().ForEach(delegate(Transform i)
|
||||
{
|
||||
i.gameObject.SetActive(true);
|
||||
});
|
||||
|
||||
StartCoroutine(LureUseGravity());
|
||||
if (isLureConnect)
|
||||
{
|
||||
fishingRope.Init(Rod);
|
||||
}
|
||||
else
|
||||
{
|
||||
fishingRope.Init(Rod);
|
||||
bobberRope.Init(Rod);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator LureUseGravity()
|
||||
{
|
||||
yield return 1;
|
||||
@@ -89,7 +121,7 @@ namespace NBF
|
||||
public void SetObiRopeStretch(float value)
|
||||
{
|
||||
Log.Error($"SetObiRopeStretch={value}");
|
||||
fishingRope.SetTargetLength(value-0.2f);
|
||||
fishingRope.SetTargetLength(value - 0.2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0eb35ab0b70344b4a2b6054f7a7ecd1b
|
||||
timeCreated: 1756822717
|
||||
@@ -1,98 +0,0 @@
|
||||
using Fantasy.Async;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Event;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public enum CameraShowMode
|
||||
{
|
||||
None = 0,
|
||||
FPP,
|
||||
TPP,
|
||||
}
|
||||
|
||||
public class CameraComponent : Entity
|
||||
{
|
||||
public CameraShowMode Mode = CameraShowMode.None;
|
||||
|
||||
private CameraAsset _cameraAsset;
|
||||
private CameraShowMode _lastMode = CameraShowMode.None;
|
||||
|
||||
public class CameraComponentAwakeSystem : AwakeSystem<CameraComponent>
|
||||
{
|
||||
protected override void Awake(CameraComponent self)
|
||||
{
|
||||
self._cameraAsset = Game.Instance.gameObject.GetComponentInChildren<CameraAsset>();
|
||||
}
|
||||
}
|
||||
|
||||
public class CameraComponentUpdateSystem : UpdateSystem<CameraComponent>
|
||||
{
|
||||
protected override void Update(CameraComponent self)
|
||||
{
|
||||
self.UpdateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
public class CameraComponentDestroySystem : DestroySystem<CameraComponent>
|
||||
{
|
||||
protected override void Destroy(CameraComponent self)
|
||||
{
|
||||
self._cameraAsset = null;
|
||||
self._lastMode = CameraShowMode.None;
|
||||
self.Mode = CameraShowMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void UpdateCamera()
|
||||
{
|
||||
if (_lastMode == Mode) return;
|
||||
if (Mode == CameraShowMode.TPP)
|
||||
{
|
||||
//第三人称视角
|
||||
SetTPPCam();
|
||||
}
|
||||
else if (Mode == CameraShowMode.FPP)
|
||||
{
|
||||
//第一人称视角
|
||||
SetFPPCam();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SetTPPCam()
|
||||
{
|
||||
_cameraAsset.fppVCam.Priority = 0;
|
||||
_cameraAsset.tppVCam.Priority = 10;
|
||||
}
|
||||
|
||||
private void SetFPPCam()
|
||||
{
|
||||
var map = App.Main.GetComponent<Map>();
|
||||
var unityComponent = map.SelfMapUnit.GetComponent<UnitUnityComponent>();
|
||||
if (unityComponent != null)
|
||||
{
|
||||
_cameraAsset.fppVCam.LookAt = unityComponent.RootAsset.FppLook;
|
||||
_cameraAsset.fppVCam.Follow = unityComponent.ModelAsset.NeckTransform;
|
||||
unityComponent.ModelAsset.LookIk.solver.target = unityComponent.RootAsset.FppLook;
|
||||
}
|
||||
|
||||
_cameraAsset.fppVCam.Priority = 10;
|
||||
_cameraAsset.tppVCam.Priority = 0;
|
||||
}
|
||||
|
||||
public void SetFppLook(Transform fppCamLook)
|
||||
{
|
||||
_cameraAsset.fppVCam.LookAt = fppCamLook;
|
||||
}
|
||||
|
||||
public void SetFppFollow(Transform fppCamFollow)
|
||||
{
|
||||
_cameraAsset.fppVCam.Follow = fppCamFollow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aee3947bbf944ecb9e955d2ac1d9e3a5
|
||||
timeCreated: 1756822741
|
||||
@@ -1,104 +0,0 @@
|
||||
// using Fantasy.Async;
|
||||
// using Fantasy.Entitas;
|
||||
// using Fantasy.Entitas.Interface;
|
||||
// using Fantasy.Event;
|
||||
// using NBC;
|
||||
// using UnityEngine;
|
||||
//
|
||||
// namespace NBF.Fishing2
|
||||
// {
|
||||
// public class CursorUIShowEvent : AsyncEventSystem<UIShowEvent>
|
||||
// {
|
||||
// protected override async FTask Handler(UIShowEvent self)
|
||||
// {
|
||||
// var cursorComponent = App.Main.GetComponent<CursorComponent>();
|
||||
// cursorComponent.UpdateCursor();
|
||||
// }
|
||||
// // protected override FTask Handler(UIShowEvent self)
|
||||
// // {
|
||||
// // throw new System.NotImplementedException();
|
||||
// // }
|
||||
// }
|
||||
//
|
||||
// public class CursorUIHideEvent : AsyncEventSystem<UIHideEvent>
|
||||
// {
|
||||
// protected override async FTask Handler(UIHideEvent self)
|
||||
// {
|
||||
// var cursorComponent = App.Main.GetComponent<CursorComponent>();
|
||||
// cursorComponent.UpdateCursor();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public class CursorComponent : Entity
|
||||
// {
|
||||
// #region System
|
||||
//
|
||||
//
|
||||
//
|
||||
// // public class CursorComponentAwakeSystem : AwakeSystem<CursorComponent>
|
||||
// // {
|
||||
// // protected override void Awake(CursorComponent self)
|
||||
// // {
|
||||
// //
|
||||
// // }
|
||||
// // }
|
||||
// //
|
||||
// // public class CursorComponentUpdateSystem : UpdateSystem<CursorComponent>
|
||||
// // {
|
||||
// // protected override void Update(CursorComponent self)
|
||||
// // {
|
||||
// // }
|
||||
// // }
|
||||
// //
|
||||
// // public class CursorComponentDestroySystem : DestroySystem<CursorComponent>
|
||||
// // {
|
||||
// // protected override void Destroy(CursorComponent self)
|
||||
// // {
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// #endregion
|
||||
//
|
||||
// public void UpdateCursor()
|
||||
// {
|
||||
// bool showCursor = false;
|
||||
// var uis = App.UI.GetAllUI();
|
||||
// foreach (var ui in uis)
|
||||
// {
|
||||
// if (ui.IsShowing && ui.IsShowCursor)
|
||||
// {
|
||||
// showCursor = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// SetMouseCursor(showCursor);
|
||||
// }
|
||||
//
|
||||
// public ControllerType controllerType = ControllerType.GamePad;
|
||||
//
|
||||
// public void SetMouseCursor(bool val)
|
||||
// {
|
||||
// Log.Info($"设置鼠标光标==={val}");
|
||||
// if (val)
|
||||
// {
|
||||
// if (controllerType == ControllerType.KeyboardMouse)
|
||||
// {
|
||||
// Cursor.visible = true;
|
||||
// }
|
||||
//
|
||||
// Cursor.lockState = CursorLockMode.None;
|
||||
// }
|
||||
// else if (controllerType == ControllerType.KeyboardMouse)
|
||||
// {
|
||||
// Cursor.visible = false;
|
||||
// }
|
||||
//
|
||||
// Cursor.visible = val;
|
||||
// if (!val)
|
||||
// {
|
||||
// Cursor.lockState = CursorLockMode.Confined;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a04f3272f2604244b8cd9d9923bb35b0
|
||||
timeCreated: 1765374579
|
||||
@@ -1,222 +0,0 @@
|
||||
using System;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public enum ControllerType
|
||||
{
|
||||
KeyboardMouse = 0,
|
||||
GamePad = 1
|
||||
}
|
||||
|
||||
public class InputComponent : Entity
|
||||
{
|
||||
public PlayerInputControl PlayerInputControl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行输入事件
|
||||
/// </summary>
|
||||
public event Action<string> OnUIPerformed;
|
||||
|
||||
/// <summary>
|
||||
/// 执行输入事件完毕
|
||||
/// </summary>
|
||||
public event Action<string> OnUICanceled;
|
||||
|
||||
/// <summary>
|
||||
/// 执行输入事件
|
||||
/// </summary>
|
||||
public event Action<string> OnPlayerPerformed;
|
||||
|
||||
/// <summary>
|
||||
/// 执行输入事件完毕
|
||||
/// </summary>
|
||||
public event Action<string> OnPlayerCanceled;
|
||||
|
||||
/// <summary>
|
||||
/// 执行输入事件
|
||||
/// </summary>
|
||||
public event Action<InputAction.CallbackContext> OnPlayerValuePerformed;
|
||||
|
||||
/// <summary>
|
||||
/// 执行输入事件完毕
|
||||
/// </summary>
|
||||
public event Action<InputAction.CallbackContext> OnPlayerValueCanceled;
|
||||
|
||||
/// <summary>
|
||||
/// 触发交互游戏对象
|
||||
/// </summary>
|
||||
public event Action<InteractiveObject> OnInteractiveObjectAction;
|
||||
|
||||
/// <summary>
|
||||
/// 手柄输入
|
||||
/// </summary>
|
||||
public static bool IsControllerInput;
|
||||
|
||||
/// <summary>
|
||||
/// ui阻止游戏输入
|
||||
/// </summary>
|
||||
public static bool IsUIStopInput;
|
||||
|
||||
|
||||
#region Event
|
||||
|
||||
public class InputComponentAwakeSystem : AwakeSystem<InputComponent>
|
||||
{
|
||||
protected override void Awake(InputComponent self)
|
||||
{
|
||||
self.PlayerInputControl = new PlayerInputControl();
|
||||
self.PlayerInputControl.Enable();
|
||||
|
||||
foreach (var actionMap in self.PlayerInputControl.asset.actionMaps)
|
||||
{
|
||||
actionMap.Enable();
|
||||
if (actionMap.name == "UI")
|
||||
{
|
||||
foreach (var action in actionMap.actions)
|
||||
{
|
||||
if (action.type == InputActionType.Button)
|
||||
{
|
||||
action.performed += self.OnUIButtonPerformed;
|
||||
action.canceled += self.OnUIButtonCanceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (actionMap.name == "Player")
|
||||
{
|
||||
foreach (var action in actionMap.actions)
|
||||
{
|
||||
if (action.type == InputActionType.Button)
|
||||
{
|
||||
action.performed += self.OnPlayerButtonPerformed;
|
||||
action.canceled += self.OnPlayerButtonCanceled;
|
||||
}
|
||||
else if (action.type == InputActionType.Value)
|
||||
{
|
||||
action.performed += self.OnInputPlayerValuePerformed;
|
||||
action.canceled += self.OnInputPlayerValueCanceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InputComponentDestroySystem : DestroySystem<InputComponent>
|
||||
{
|
||||
protected override void Destroy(InputComponent self)
|
||||
{
|
||||
foreach (var actionMap in self.PlayerInputControl.asset.actionMaps)
|
||||
{
|
||||
actionMap.Enable();
|
||||
if (actionMap.name == "UI")
|
||||
{
|
||||
foreach (var action in actionMap.actions)
|
||||
{
|
||||
if (action.type == InputActionType.Button)
|
||||
{
|
||||
action.performed -= self.OnUIButtonPerformed;
|
||||
action.canceled -= self.OnUIButtonCanceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (actionMap.name == "Player")
|
||||
{
|
||||
foreach (var action in actionMap.actions)
|
||||
{
|
||||
if (action.type == InputActionType.Button)
|
||||
{
|
||||
action.performed -= self.OnPlayerButtonPerformed;
|
||||
action.canceled -= self.OnPlayerButtonCanceled;
|
||||
}
|
||||
else if (action.type == InputActionType.Value)
|
||||
{
|
||||
action.performed -= self.OnInputPlayerValuePerformed;
|
||||
action.canceled -= self.OnInputPlayerValueCanceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnUIButtonPerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
OnUIPerformed?.Invoke(context.action.name);
|
||||
}
|
||||
|
||||
private void OnUIButtonCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
OnUICanceled?.Invoke(context.action.name);
|
||||
}
|
||||
|
||||
private void OnPlayerButtonPerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
if (IsUIStopInput) return;
|
||||
var actionName = context.action.name;
|
||||
// if (actionName == "Op1")
|
||||
// {
|
||||
// OnOp1Action?.Invoke(true);
|
||||
// }
|
||||
// else if (actionName == "Op2")
|
||||
// {
|
||||
// OnOp2Action?.Invoke(true);
|
||||
// }
|
||||
|
||||
OnPlayerPerformed?.Invoke(actionName);
|
||||
}
|
||||
|
||||
private void OnPlayerButtonCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
if (IsUIStopInput) return;
|
||||
var actionName = context.action.name;
|
||||
// if (actionName == "Op1")
|
||||
// {
|
||||
// OnOp1Action?.Invoke(false);
|
||||
// }
|
||||
// else if (actionName == "Op2")
|
||||
// {
|
||||
// OnOp2Action?.Invoke(false);
|
||||
// }
|
||||
//
|
||||
OnPlayerCanceled?.Invoke(actionName);
|
||||
}
|
||||
|
||||
private void OnInputPlayerValuePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
if (IsUIStopInput) return;
|
||||
OnPlayerValuePerformed?.Invoke(context);
|
||||
}
|
||||
|
||||
private void OnInputPlayerValueCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
if (IsUIStopInput) return;
|
||||
OnPlayerValueCanceled?.Invoke(context);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public Vector2 GetMovementInput()
|
||||
{
|
||||
if (IsUIStopInput) return Vector2.zero;
|
||||
return PlayerInputControl.Player.Move?.ReadValue<Vector2>() ?? Vector2.zero;
|
||||
}
|
||||
|
||||
public Vector2 GetLookInput()
|
||||
{
|
||||
if (IsUIStopInput) return Vector2.zero;
|
||||
return PlayerInputControl.Player.Look?.ReadValue<Vector2>() ?? Vector2.zero;
|
||||
}
|
||||
|
||||
public void SendUIInput(string actionName)
|
||||
{
|
||||
OnUIPerformed?.Invoke(actionName);
|
||||
OnUICanceled?.Invoke(actionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09132878c89a444a88421b7434394235
|
||||
timeCreated: 1756826439
|
||||
@@ -1,9 +0,0 @@
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class SettingComponent : Entity
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c6adcf67ef545f99c590d1078a76eea
|
||||
timeCreated: 1756826460
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c1174e9753b43ac9dd5fa664e92021b
|
||||
timeCreated: 1756450590
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Async;
|
||||
using NBC;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public static class MoveHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 可以多次调用,多次调用的话会取消上一次的协程
|
||||
/// </summary>
|
||||
/// <param name="unit"></param>
|
||||
/// <param name="targetPos"></param>
|
||||
/// <returns></returns>
|
||||
public static async FTask<int> MoveToAsync(this MapUnit unit, float3 targetPos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static async FTask MoveToAsync(this MapUnit unit, List<float3> path)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ce11e50e0d749bfa5915208b1ce1a44
|
||||
timeCreated: 1756822516
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public static class PathHelper
|
||||
{
|
||||
public static string GetFullPath(string path)
|
||||
{
|
||||
return Path.Combine("gfx", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 774fd7a393874949863a694a79823e1c
|
||||
timeCreated: 1761145384
|
||||
@@ -1,83 +0,0 @@
|
||||
using System.Linq;
|
||||
using Fantasy;
|
||||
using NBC;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public static class ProtoHelper
|
||||
{
|
||||
public static MapUnitInfo ToMapUnitInfo(this RoleInfo self)
|
||||
{
|
||||
MapUnitInfo mapUnit = new MapUnitInfo();
|
||||
mapUnit.Id = self.RoleId;
|
||||
mapUnit.RoleInfo = self.ToSimpleInfo();
|
||||
// mapUnit.Gears = self.Gears;
|
||||
return mapUnit;
|
||||
}
|
||||
|
||||
public static RoleSimpleInfo ToSimpleInfo(this RoleInfo self)
|
||||
{
|
||||
var ret = new RoleSimpleInfo();
|
||||
ret.NickName = self.BaseInfo.NickName;
|
||||
ret.RoleId = self.RoleId;
|
||||
ret.Country = self.BaseInfo.Country;
|
||||
ret.Head = self.BaseInfo.Head;
|
||||
ret.Level = self.BaseInfo.Level;
|
||||
// ret.Vip = self.BaseInfo.Vip;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#region Vector
|
||||
|
||||
public static Vector3Info ToVector3Info(this Vector3 self)
|
||||
{
|
||||
var ret = new Vector3Info();
|
||||
ret.x = self.x;
|
||||
ret.y = self.y;
|
||||
ret.z = self.z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
public static QuaternionInfo ToQuaternionInfo(this Quaternion self)
|
||||
{
|
||||
var ret = new QuaternionInfo();
|
||||
ret.x = self.x;
|
||||
ret.y = self.y;
|
||||
ret.z = self.z;
|
||||
ret.w = self.w;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 ToVector3(this Vector3Info self)
|
||||
{
|
||||
var ret = new Vector3
|
||||
{
|
||||
x = self.x,
|
||||
y = self.y,
|
||||
z = self.z
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
public static Quaternion ToQuaternion(this QuaternionInfo self)
|
||||
{
|
||||
var ret = new Quaternion
|
||||
{
|
||||
x = self.x,
|
||||
y = self.y,
|
||||
z = self.z,
|
||||
w = self.w
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 850c683faae3419abd3693f7e87accae
|
||||
timeCreated: 1756738767
|
||||
@@ -1,25 +0,0 @@
|
||||
using Fantasy.Async;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public static class UnitHelper
|
||||
{
|
||||
public static async FTask InitMapUnit(this MapUnit self)
|
||||
{
|
||||
await FTask.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
public static bool IsSelf(this MapUnit self)
|
||||
{
|
||||
if (self.Id == Game.SelfId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82c91df89554417c87a3658709ef406d
|
||||
timeCreated: 1756450600
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9626380655a42298daf90e7333172ae
|
||||
timeCreated: 1756363915
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9720afaa3bc94081b63a7c0571e4c86a
|
||||
timeCreated: 1757251153
|
||||
@@ -1,20 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network;
|
||||
using Fantasy.Network.Interface;
|
||||
using NBF.Fishing2;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class Map2C_ChangeMapHandler : Message<Map2C_ChangeMap>
|
||||
{
|
||||
protected override async FTask Run(Session session, Map2C_ChangeMap message)
|
||||
{
|
||||
Log.Info($"收到地图切换消息=={message.MapId}");
|
||||
// await MapHelper.ChangeMap(message.MapId);
|
||||
|
||||
// await MapHelper.CreateRoomTest(message.MapId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9aca13592484450582e818dd128a23c2
|
||||
timeCreated: 1756301493
|
||||
@@ -1,32 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network;
|
||||
using Fantasy.Network.Interface;
|
||||
using NBC;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class Map2C_RoleEnterMapNotifyHandler : Message<Map2C_RoleEnterRoomNotify>
|
||||
{
|
||||
protected override async FTask Run(Session session, Map2C_RoleEnterRoomNotify message)
|
||||
{
|
||||
Log.Info($"收到进入房间推送 id={message.Info.Id} ");
|
||||
var map = App.Main.GetComponent<Map>();
|
||||
if (map == null || !map.IsRoomMap)
|
||||
{
|
||||
Log.Info("房间不是好友房间,不处理进入请求");
|
||||
return;
|
||||
}
|
||||
|
||||
var info = message.Info;
|
||||
var unit = map.GetUnit(info.Id);
|
||||
if (unit == null)
|
||||
{
|
||||
unit = map.CreateMapUnit(info);
|
||||
}
|
||||
|
||||
await unit.CreateView();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0934eeab5b8445b824f1337f774379e
|
||||
timeCreated: 1757251141
|
||||
@@ -1,27 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network;
|
||||
using Fantasy.Network.Interface;
|
||||
using NBC;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class Map2C_RoleExitMapNotifyHandler : Message<Map2C_RoleExitRoomNotify>
|
||||
{
|
||||
protected override async FTask Run(Session session, Map2C_RoleExitRoomNotify message)
|
||||
{
|
||||
Log.Info($"收到离开房间推送 id={message.Id} ");
|
||||
var map = App.Main.GetComponent<Map>();
|
||||
if (map == null)
|
||||
{
|
||||
Log.Info("地图不存在,不处理退出请求");
|
||||
return;
|
||||
}
|
||||
if (map.Units.Remove(message.Id, out var unit))
|
||||
{
|
||||
unit.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18ae467167c44db1873fee88067d2f9a
|
||||
timeCreated: 1757251193
|
||||
@@ -1,94 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class Map : Entity
|
||||
{
|
||||
public int MapId;
|
||||
|
||||
public string RoomCode;
|
||||
|
||||
/// <summary>
|
||||
/// 自己的实体id
|
||||
/// </summary>
|
||||
public long SelfId;
|
||||
|
||||
/// <summary>
|
||||
/// 好友房地图
|
||||
/// </summary>
|
||||
public bool IsRoomMap => !string.IsNullOrEmpty(RoomCode);
|
||||
|
||||
/// <summary>
|
||||
/// 地图中的单位
|
||||
/// </summary>
|
||||
public Dictionary<long, MapUnit> Units = new Dictionary<long, MapUnit>();
|
||||
|
||||
/// <summary>
|
||||
/// 自己的实体
|
||||
/// </summary>
|
||||
public MapUnit SelfMapUnit => GetUnit(SelfId);
|
||||
|
||||
|
||||
#region System
|
||||
|
||||
public class MapDestroySystem : DestroySystem<Map>
|
||||
{
|
||||
protected override void Destroy(Map self)
|
||||
{
|
||||
self.MapId = 0;
|
||||
self.SelfId = 0;
|
||||
self.RoomCode = string.Empty;
|
||||
self.Units.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public MapUnit CreateMapUnit(MapUnitInfo unitInfo)
|
||||
{
|
||||
var mapUnit = Create<MapUnit>(Scene, unitInfo.Id, true, true);
|
||||
mapUnit.SetUnitInfo(unitInfo);
|
||||
Add(mapUnit);
|
||||
return mapUnit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个单位
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public MapUnit GetUnit(long id)
|
||||
{
|
||||
return Units.GetValueOrDefault(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进入地图
|
||||
/// </summary>
|
||||
/// <param name="map"></param>
|
||||
/// <param name="unit"></param>
|
||||
/// <returns></returns>
|
||||
public bool Add(MapUnit unit)
|
||||
{
|
||||
Units.Add(unit.Id, unit);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开地图
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public bool Remove(long id)
|
||||
{
|
||||
return Units.Remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2acb8a2309ee4443a812939b0e02c18f
|
||||
timeCreated: 1756049289
|
||||
@@ -1,11 +0,0 @@
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
/// <summary>
|
||||
/// 地图管理组件
|
||||
/// </summary>
|
||||
public class MapManageComponent : Entity
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 226c840e80f840ae8a4ff54bc7c6645a
|
||||
timeCreated: 1756304063
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b35630cbcbbb4792a821de847fabbd69
|
||||
timeCreated: 1757820526
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c197c410c838437996d832515a62026e
|
||||
timeCreated: 1757835465
|
||||
@@ -1,35 +0,0 @@
|
||||
// using System.Collections.Generic;
|
||||
// using Fantasy;
|
||||
// using Fantasy.Event;
|
||||
//
|
||||
// namespace NBF.Fishing2
|
||||
// {
|
||||
// public class NumericChangeEvent : EventSystem<NumericChange>
|
||||
// {
|
||||
// protected override void Handler(NumericChange self)
|
||||
// {
|
||||
// if (self.Old == self.New) return;
|
||||
// if (self.NumericType == NumericType.Flashlight)
|
||||
// {
|
||||
// var flashlight = self.MapUnit.GetComponent<FlashlightComponent>();
|
||||
// flashlight.Change(self.New);
|
||||
// if (self.MapUnit.IsSelf())
|
||||
// {
|
||||
// var list = new List<KeyValueInt64>
|
||||
// {
|
||||
// new KeyValueInt64()
|
||||
// {
|
||||
// Key = self.NumericType,
|
||||
// Value = self.New
|
||||
// }
|
||||
// };
|
||||
// //如果是自己的,则同步给其他玩家
|
||||
// Net.Send(new C2Map_RolePropertyChange()
|
||||
// {
|
||||
// Propertys = list
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dae2fd757bc46b7b47a7b548b36ed54
|
||||
timeCreated: 1757835696
|
||||
@@ -1,33 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network;
|
||||
using Fantasy.Network.Interface;
|
||||
using NBC;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class Map2C_LookNotifyHandler : Message<Map2C_LookeNotify>
|
||||
{
|
||||
protected override async FTask Run(Session session, Map2C_LookeNotify message)
|
||||
{
|
||||
Log.Info($"收到朝向推送 id={message.Id} ");
|
||||
var map = App.Main.GetComponent<Map>();
|
||||
var unit = map.Units[message.Id];
|
||||
if (unit.IsSelf())
|
||||
{
|
||||
Log.Info("自己的旋转消息,不处理");
|
||||
}
|
||||
else
|
||||
{
|
||||
var moveComponent = unit.GetComponent<CharacterControllerComponent>();
|
||||
if (moveComponent != null)
|
||||
{
|
||||
moveComponent.OnServerLook(message.Rotation.ToVector3(), message.Timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
await FTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1f00b074c7f48248773361036d3bfcf
|
||||
timeCreated: 1757238435
|
||||
@@ -1,36 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network;
|
||||
using Fantasy.Network.Interface;
|
||||
using NBC;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class Map2C_MoveNotifyHandler : Message<Map2C_MoveNotify>
|
||||
{
|
||||
protected override async FTask Run(Session session, Map2C_MoveNotify message)
|
||||
{
|
||||
Log.Info($"收到移动推送 id={message.Id} stop={message.IsStop}");
|
||||
// session.Scene
|
||||
// session.Scene.GetComponent<MapUnitInfo>(message.Id),
|
||||
var map = App.Main.GetComponent<Map>();
|
||||
var unit = map.Units[message.Id];
|
||||
var moveComponent = unit.GetComponent<CharacterControllerComponent>();
|
||||
if (moveComponent != null)
|
||||
{
|
||||
if (message.IsStop)
|
||||
{
|
||||
moveComponent.OnServerStopMove(message.Position.ToVector3(), message.Timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
moveComponent.OnServerStartMove(message.Position.ToVector3(),
|
||||
message.Direction.ToVector3(), 3, message.Timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
await FTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2306a332c3f842e78fd8d70c9ef1f8ed
|
||||
timeCreated: 1757148423
|
||||
@@ -1,26 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network;
|
||||
using Fantasy.Network.Interface;
|
||||
using NBC;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class Map2C_RolePropertyChangeNotifyHandler : Message<Map2C_RolePropertyChangeNotify>
|
||||
{
|
||||
protected override async FTask Run(Session session, Map2C_RolePropertyChangeNotify message)
|
||||
{
|
||||
Log.Info($"收到角色属性推送 id={message.Id}");
|
||||
var map = App.Main.GetComponent<Map>();
|
||||
var unit = map.Units[message.Id];
|
||||
var numericComponent = unit.GetComponent<NumericComponent>();
|
||||
foreach (var property in message.Propertys)
|
||||
{
|
||||
numericComponent.Set(property.Key, property.Value);
|
||||
}
|
||||
|
||||
await FTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b507863390534ecca584e3a787180493
|
||||
timeCreated: 1757820797
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53262d3faa5141deb0c8809a4354daa0
|
||||
timeCreated: 1756820602
|
||||
@@ -1,58 +0,0 @@
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerArm : MonoBehaviour
|
||||
{
|
||||
public bool IsLeft;
|
||||
public LimbIK IK;
|
||||
public Transform RodContainer;
|
||||
public Transform LeftRigMagnet;
|
||||
public FingerRig FingerRig;
|
||||
public PlayerShoulder Shoulder;//PlayerShoulder
|
||||
|
||||
[HideInInspector] public float interactionTargetWeight;
|
||||
|
||||
|
||||
public void SetReelHandle(ReelAsset asset)
|
||||
{
|
||||
IK.solver.target = asset.handle;
|
||||
IK.enabled = true;
|
||||
|
||||
// var fingers = FingerRig.fingers;
|
||||
// foreach (var finger in fingers)
|
||||
// {
|
||||
// finger.target = asset.handleEnd;
|
||||
// }
|
||||
|
||||
// // 启用整体控制
|
||||
// FingerRig.weight = 1f;
|
||||
//
|
||||
// // 绑定大拇指和食指的目标
|
||||
// FingerRig.fingers[0].target = asset.handleEnd; // Thumb
|
||||
// FingerRig.fingers[1].target = asset.handleEnd; // Index
|
||||
//
|
||||
// FingerRig.fingers[0].weight = 1f;
|
||||
// FingerRig.fingers[1].weight = 1f;
|
||||
|
||||
// 其余手指握拳(不绑定 target)
|
||||
for (int i = 2; i < 5; i++)
|
||||
{
|
||||
FingerRig.fingers[i].target = null;
|
||||
FingerRig.fingers[i].weight = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
public void MoveTowardsInteraction()
|
||||
{
|
||||
if (!IK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IK.solver.SetIKPositionWeight(Mathf.MoveTowards(IK.solver.IKPositionWeight,
|
||||
interactionTargetWeight, Time.deltaTime * 2f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed33e261a2784ee0814ceaa6c88aefdf
|
||||
timeCreated: 1756821001
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerShoulder : MonoBehaviour
|
||||
{
|
||||
private Vector3 startEulerAngles;
|
||||
private const int MaxAngle = 30;
|
||||
private const int MinAngle = -30;
|
||||
|
||||
|
||||
public float TestZ;
|
||||
private void Awake()
|
||||
{
|
||||
startEulerAngles = transform.localEulerAngles;
|
||||
}
|
||||
|
||||
public void SetCameraEulerAngleX(float value)
|
||||
{
|
||||
value = (value > 180f) ? value - 360f : value;
|
||||
Debug.Log($"value={value}");
|
||||
var addValue = value * -1;
|
||||
if (addValue > MaxAngle)
|
||||
{
|
||||
addValue = MaxAngle;
|
||||
}
|
||||
else if (addValue < MinAngle)
|
||||
{
|
||||
addValue = MinAngle;
|
||||
}
|
||||
|
||||
transform.localEulerAngles =
|
||||
new Vector3(addValue + startEulerAngles.x, startEulerAngles.y, TestZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f85286904d2d45738c4b415f3503d4ab
|
||||
timeCreated: 1756820965
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fb0ee12d9cf40408478e8f9ad9aafdd
|
||||
timeCreated: 1755915944
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35bf130c632b4a31b064a6d0706aba65
|
||||
timeCreated: 1757835845
|
||||
@@ -1,69 +0,0 @@
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
/// <summary>
|
||||
/// 手电筒组件
|
||||
/// </summary>
|
||||
public class FlashlightComponent : Entity
|
||||
{
|
||||
private GameObject _fishingLight;
|
||||
|
||||
|
||||
public class FlashlightComponentAwakeSystem : AwakeSystem<FlashlightComponent>
|
||||
{
|
||||
protected override void Awake(FlashlightComponent self)
|
||||
{
|
||||
var numericComponent = self.Parent.GetComponent<NumericComponent>();
|
||||
var unityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
// self._fishingLight = unityComponent.Asset.FishingLight;
|
||||
// self.Change(numericComponent[NumericType.Flashlight]);
|
||||
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerCanceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FlashlightComponentDestroySystem : DestroySystem<FlashlightComponent>
|
||||
{
|
||||
protected override void Destroy(FlashlightComponent self)
|
||||
{
|
||||
self._fishingLight = null;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
if (inputComponent != null)
|
||||
{
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerCanceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnPlayerCanceled(string action)
|
||||
{
|
||||
if (action == InputDef.Player.UseTorch)
|
||||
{
|
||||
var numericComponent = Parent.GetComponent<NumericComponent>();
|
||||
if (numericComponent != null)
|
||||
{
|
||||
var oldValue = numericComponent[NumericType.Flashlight];
|
||||
numericComponent[NumericType.Flashlight] = oldValue > 0 ? 0 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Change(long value)
|
||||
{
|
||||
_fishingLight.SetActive(value > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b498c6d3db5b4d44a1dc99b547416d59
|
||||
timeCreated: 1757836076
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c61b32e7992466f9771eac80763078e
|
||||
timeCreated: 1765523393
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70bbe8d6e0c04cdaa553cacaee37fe59
|
||||
timeCreated: 1755921259
|
||||
@@ -1,16 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
/// <summary>
|
||||
/// 玩家组件
|
||||
/// </summary>
|
||||
public class MapUnitGear : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 绑定的子组件
|
||||
/// </summary>
|
||||
public List<MapUnitGearPart> Binding = new List<MapUnitGearPart>();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01c5cf0e015042fbae5000cff14bb419
|
||||
timeCreated: 1766325287
|
||||
@@ -1,12 +0,0 @@
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class MapUnitGearPart : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置表id
|
||||
/// </summary>
|
||||
public int ConfigId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a83db5681be745a3b692da5c82496a40
|
||||
timeCreated: 1766325663
|
||||
@@ -1,120 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
/// <summary>
|
||||
/// 单位
|
||||
/// </summary>
|
||||
public class MapUnit : Entity
|
||||
{
|
||||
public int ConfigId { get; set; } //配置表id
|
||||
|
||||
/// <summary>
|
||||
/// 钓组信息
|
||||
/// </summary>
|
||||
public List<MapUnitGear> Gears = new List<MapUnitGear>();
|
||||
|
||||
/// <summary>
|
||||
/// 是否在地面
|
||||
/// </summary>
|
||||
public bool IsGrounded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否在水里
|
||||
/// </summary>
|
||||
public bool IsInWater { get; set; }
|
||||
|
||||
public float Speed { get; set; }
|
||||
public float RotationSpeed { get; set; }
|
||||
|
||||
private Vector3 position; //坐标
|
||||
|
||||
public Vector3 Position
|
||||
{
|
||||
get => position;
|
||||
set
|
||||
{
|
||||
// Vector3 oldPos = position;
|
||||
position = value;
|
||||
// Scene.EventComponent.Publish(new ChangePosition() { MapUnit = this, OldPos = oldPos });
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Forward
|
||||
{
|
||||
get => math.mul(Rotation, math.forward());
|
||||
set => Rotation = Quaternion.LookRotation(value, math.up());
|
||||
}
|
||||
|
||||
private Quaternion rotation;
|
||||
|
||||
public Quaternion Rotation
|
||||
{
|
||||
get => rotation;
|
||||
set
|
||||
{
|
||||
rotation = value;
|
||||
// Scene.EventComponent.Publish(new ChangeRotation() { MapUnit = this });
|
||||
}
|
||||
}
|
||||
|
||||
public MapUnitState State { get; set; }
|
||||
|
||||
public string StateArgs { get; set; }
|
||||
|
||||
#region System
|
||||
|
||||
public class MapUnitDestroySystem : DestroySystem<MapUnit>
|
||||
{
|
||||
protected override void Destroy(MapUnit self)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void ChangeState(MapUnitState state, string args)
|
||||
{
|
||||
Scene.EventComponent.Publish(new ChangeState() { MapUnit = this, State = state, Args = args });
|
||||
}
|
||||
|
||||
|
||||
public void SetUnitInfo(MapUnitInfo unitInfo)
|
||||
{
|
||||
GetOrAddComponent<ObjectWait>();
|
||||
var unitBasic = GetOrAddComponent<MapUnitBasic>();
|
||||
unitBasic.UpdateInfo(unitInfo);
|
||||
|
||||
// unitInfo.Gears
|
||||
|
||||
var numericComponent = GetOrAddComponent<NumericComponent>();
|
||||
foreach (var kv in unitInfo.Propertys)
|
||||
{
|
||||
numericComponent.Set(kv.Key, kv.Value);
|
||||
}
|
||||
}
|
||||
|
||||
#region View
|
||||
|
||||
public async FTask CreateView()
|
||||
{
|
||||
var unitUnity = GetComponent<UnitUnityComponent>();
|
||||
if (unitUnity != null)
|
||||
{
|
||||
unitUnity.Dispose();
|
||||
}
|
||||
|
||||
unitUnity = AddComponent<UnitUnityComponent>();
|
||||
await unitUnity.InitUnityObject();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff176fc098254fe2a1b48ea26eaf8857
|
||||
timeCreated: 1755915448
|
||||
@@ -1,39 +0,0 @@
|
||||
using Fantasy;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class MapUnitBasic : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 昵称
|
||||
/// </summary>
|
||||
public string NickName;
|
||||
|
||||
/// <summary>
|
||||
/// 头像
|
||||
/// </summary>
|
||||
public string Head;
|
||||
|
||||
/// <summary>
|
||||
/// 国家
|
||||
/// </summary>
|
||||
public string Country;
|
||||
|
||||
/// <summary>
|
||||
/// 等级
|
||||
/// </summary>
|
||||
public int Level;
|
||||
|
||||
|
||||
public void UpdateInfo(MapUnitInfo mapUnitInfo)
|
||||
{
|
||||
if (mapUnitInfo.RoleInfo == null) return;
|
||||
NickName = mapUnitInfo.RoleInfo.NickName;
|
||||
Head = mapUnitInfo.RoleInfo.Head;
|
||||
Country = mapUnitInfo.RoleInfo.Country;
|
||||
Level = mapUnitInfo.RoleInfo.Level;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fac7cf28f53b4a929d2584c9a95fd242
|
||||
timeCreated: 1756881253
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 309507c5427f4a95bb64f526ce60ded0
|
||||
timeCreated: 1757820516
|
||||
@@ -1,427 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct MoveState
|
||||
{
|
||||
public Vector3 startPosition; // 开始移动时的位置
|
||||
public Vector3 moveDirection; // 移动方向(标准化向量)
|
||||
public float moveSpeed; // 移动速度
|
||||
public bool isMoving; // 是否正在移动
|
||||
public double serverTimestamp; // 服务器时间戳
|
||||
}
|
||||
|
||||
public class CharacterControllerComponent : Entity
|
||||
{
|
||||
public bool IsSelf;
|
||||
public bool Run;
|
||||
public CharacterController characterController;
|
||||
public PlayerModelAsset PlayerModelAsset;
|
||||
|
||||
public readonly Queue<MoveState> MoveStateQueue = new Queue<MoveState>();
|
||||
|
||||
public Transform transform => characterController.transform;
|
||||
private MoveState currentMoveState;
|
||||
|
||||
// private Vector3 networkFacingDirection;
|
||||
|
||||
// 添加目标位置和旋转用于插值
|
||||
private Vector3 targetPosition;
|
||||
private Quaternion targetRotation;
|
||||
|
||||
// 插值平滑参数
|
||||
public float positionLerpSpeed = 10f;
|
||||
public float rotationLerpSpeed = 10f;
|
||||
|
||||
|
||||
private float currentSpeed = 0f;
|
||||
private float acceleration = 10f; // 加速度
|
||||
|
||||
/// <summary>
|
||||
/// 重力加速度
|
||||
/// </summary>
|
||||
private float gravity = 9.81f;
|
||||
|
||||
|
||||
private Vector3 currentVelocity = Vector3.zero;
|
||||
private float verticalVelocity = 0f;
|
||||
|
||||
private float groundedGravity = -0.5f; // 小的向下力确保角色保持在地面
|
||||
private float airControl = 0.5f; // 空中控制系数
|
||||
|
||||
#region System
|
||||
|
||||
public class MoveComponentDestroySystem : DestroySystem<CharacterControllerComponent>
|
||||
{
|
||||
protected override void Destroy(CharacterControllerComponent self)
|
||||
{
|
||||
self.characterController = null;
|
||||
self.IsSelf = false;
|
||||
self.Run = false;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
if (inputComponent != null)
|
||||
{
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerCanceled;
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerPerformed;
|
||||
|
||||
inputComponent.OnPlayerValueCanceled -= self.OnPlayerValueCanceled;
|
||||
inputComponent.OnPlayerValuePerformed -= self.OnPlayerValuePerformed;
|
||||
}
|
||||
}
|
||||
|
||||
self.PlayerModelAsset = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class MoveComponentAwakeSystem : AwakeSystem<CharacterControllerComponent>
|
||||
{
|
||||
protected override void Awake(CharacterControllerComponent self)
|
||||
{
|
||||
var unitUnityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self.PlayerModelAsset = unitUnityComponent.ModelAsset;
|
||||
self.characterController = unitUnityComponent.GameObject.GetComponent<CharacterController>();
|
||||
self.lastSyncedFacing = self.characterController.transform.forward;
|
||||
// 初始化目标位置和旋转
|
||||
self.targetPosition = self.characterController.transform.position;
|
||||
self.targetRotation = self.characterController.transform.rotation;
|
||||
self.characterController.enabled = true;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
self.IsSelf = true;
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerCanceled;
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerPerformed;
|
||||
|
||||
inputComponent.OnPlayerValueCanceled += self.OnPlayerValueCanceled;
|
||||
inputComponent.OnPlayerValuePerformed += self.OnPlayerValuePerformed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MoveComponentUpdateSystem : UpdateSystem<CharacterControllerComponent>
|
||||
{
|
||||
protected override void Update(CharacterControllerComponent self)
|
||||
{
|
||||
self.ProcessMoveStates();
|
||||
self.CheckRotationSync();
|
||||
// 插值更新位置和旋转
|
||||
self.InterpolatePositionAndRotation();
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
mapUnit.Position = self.characterController.transform.position;
|
||||
mapUnit.Rotation = self.characterController.transform.rotation;
|
||||
var f = mapUnit.Forward;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Input
|
||||
|
||||
private void OnPlayerPerformed(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Run = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerCanceled(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Run = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValueCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
var name = context.action.name;
|
||||
if (name == InputDef.Player.Move)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
SendMoveMessage(v2, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValuePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
// var mapUnit = Parent as MapUnit;
|
||||
// Log.Info($"OnPlayerValuePerformed IsSelf={mapUnit.IsSelf()} id={mapUnit.Id}");
|
||||
var name = context.action.name;
|
||||
if (name == InputDef.Player.Move)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
SendMoveMessage(v2, false);
|
||||
}
|
||||
else if (name == InputDef.Player.Look)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
UpdatePlayerRotation(v2);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Message
|
||||
|
||||
private void SendMoveMessage(Vector3 movementInput, bool isStop = false)
|
||||
{
|
||||
var mapUnit = Parent as MapUnit;
|
||||
|
||||
Vector3 movementDirection = Vector3.zero;
|
||||
|
||||
// 发送本地相对坐标而不是世界坐标
|
||||
if (!isStop)
|
||||
{
|
||||
movementDirection = new Vector3(movementInput.x, 0, movementInput.y);
|
||||
}
|
||||
|
||||
Net.Send(new C2Map_Move()
|
||||
{
|
||||
Direction = movementDirection.ToVector3Info(),
|
||||
IsStop = isStop,
|
||||
IsRun = Run,
|
||||
Timestamp = TimeHelper.Now,
|
||||
Position = mapUnit.Position.ToVector3Info(),
|
||||
Rotation = mapUnit.Forward.ToVector3Info(),
|
||||
});
|
||||
}
|
||||
|
||||
private void SendLookMessage()
|
||||
{
|
||||
Log.Info("发送朝向同步消息");
|
||||
Net.Send(new C2Map_Look()
|
||||
{
|
||||
Rotation = characterController.transform.forward.ToVector3Info(),
|
||||
Timestamp = TimeHelper.Now
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收服务器移动开始通知
|
||||
/// </summary>
|
||||
/// <param name="startPosition"></param>
|
||||
/// <param name="moveDirection"></param>
|
||||
/// <param name="speed"></param>
|
||||
/// <param name="timestamp"></param>
|
||||
public void OnServerStartMove(Vector3 startPosition, Vector3 moveDirection, float speed, double timestamp)
|
||||
{
|
||||
MoveState moveState = new MoveState
|
||||
{
|
||||
startPosition = startPosition,
|
||||
moveDirection = moveDirection.normalized,
|
||||
moveSpeed = speed,
|
||||
isMoving = true,
|
||||
serverTimestamp = timestamp
|
||||
};
|
||||
|
||||
MoveStateQueue.Enqueue(moveState);
|
||||
Log.Info($"MoveStateQueue Count={MoveStateQueue.Count}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收服务器移动停止通知
|
||||
/// </summary>
|
||||
/// <param name="finalPosition"></param>
|
||||
/// <param name="timestamp"></param>
|
||||
public void OnServerStopMove(Vector3 finalPosition, double timestamp)
|
||||
{
|
||||
MoveState moveState = new MoveState
|
||||
{
|
||||
startPosition = finalPosition,
|
||||
moveDirection = Vector3.zero,
|
||||
moveSpeed = 0f,
|
||||
isMoving = false,
|
||||
serverTimestamp = timestamp
|
||||
};
|
||||
|
||||
MoveStateQueue.Enqueue(moveState);
|
||||
Log.Info($"MoveStateQueue Count={MoveStateQueue.Count}");
|
||||
}
|
||||
|
||||
|
||||
public void OnServerLook(Vector3 rotation, double timestamp)
|
||||
{
|
||||
// 设置目标旋转用于插值
|
||||
targetRotation = Quaternion.LookRotation(rotation);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Move
|
||||
|
||||
private void ProcessMoveStates()
|
||||
{
|
||||
// 只有在当前状态不是移动状态时,才处理下一个状态
|
||||
if (MoveStateQueue.Count > 0)
|
||||
{
|
||||
currentMoveState = MoveStateQueue.Dequeue();
|
||||
|
||||
if (currentMoveState.isMoving)
|
||||
{
|
||||
StartMovement(currentMoveState);
|
||||
}
|
||||
else
|
||||
{
|
||||
StopMovement(currentMoveState);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果正在移动,持续更新
|
||||
if (currentMoveState.isMoving)
|
||||
{
|
||||
UpdateMovement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void StartMovement(MoveState moveState)
|
||||
{
|
||||
targetPosition = moveState.startPosition;
|
||||
Debug.Log($"开始移动 - 位置: {moveState.startPosition}");
|
||||
}
|
||||
|
||||
private void StopMovement(MoveState moveState)
|
||||
{
|
||||
targetPosition = moveState.startPosition;
|
||||
Debug.Log($"停止移动 - 最终位置: {moveState.startPosition}");
|
||||
}
|
||||
|
||||
private void UpdateMovement()
|
||||
{
|
||||
// 将本地相对方向转换为世界方向
|
||||
Vector3 localDirection = currentMoveState.moveDirection;
|
||||
Vector3 characterRight = Vector3.ProjectOnPlane(characterController.transform.right, Vector3.up).normalized;
|
||||
Vector3 characterForward = Vector3.ProjectOnPlane(characterController.transform.forward, Vector3.up).normalized;
|
||||
Vector3 movementDirection = characterForward * localDirection.z + characterRight * localDirection.x;
|
||||
|
||||
float targetSpeed = currentMoveState.moveSpeed;
|
||||
|
||||
// 平滑加速
|
||||
if (movementDirection.magnitude > 0.1f)
|
||||
{
|
||||
currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, acceleration * Time.deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSpeed = Mathf.Lerp(currentSpeed, 0f, acceleration * 2f * Time.deltaTime);
|
||||
}
|
||||
|
||||
// 处理重力
|
||||
if (characterController.isGrounded)
|
||||
{
|
||||
verticalVelocity = groundedGravity;
|
||||
|
||||
// 地面移动 - 完全控制
|
||||
currentVelocity = Vector3.Lerp(currentVelocity, movementDirection.normalized * currentSpeed,
|
||||
acceleration * Time.deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
verticalVelocity -= gravity * Time.deltaTime;
|
||||
|
||||
// 空中移动 - 有限控制
|
||||
Vector3 targetAirVelocity = movementDirection.normalized * currentSpeed * airControl;
|
||||
currentVelocity = Vector3.Lerp(currentVelocity,
|
||||
new Vector3(targetAirVelocity.x, currentVelocity.y, targetAirVelocity.z),
|
||||
acceleration * Time.deltaTime);
|
||||
}
|
||||
|
||||
// 组合移动
|
||||
Vector3 totalMovement = currentVelocity * Time.deltaTime;
|
||||
totalMovement.y = verticalVelocity * Time.deltaTime;
|
||||
|
||||
Log.Info($"移动=== Id={Parent.Id} 位置: {characterController.transform.position} 移动量: {totalMovement}");
|
||||
|
||||
characterController.Move(totalMovement);
|
||||
}
|
||||
|
||||
// 添加位置和旋转插值方法
|
||||
private void InterpolatePositionAndRotation()
|
||||
{
|
||||
// 只对非本地玩家进行插值
|
||||
if (!IsSelf)
|
||||
{
|
||||
// 插值位置
|
||||
// characterController.transform.position = Vector3.Lerp(
|
||||
// characterController.transform.position,
|
||||
// targetPosition,
|
||||
// positionLerpSpeed * Time.deltaTime);
|
||||
|
||||
// 插值旋转 - 使用更平滑的插值方法
|
||||
characterController.transform.rotation = Quaternion.Slerp(
|
||||
characterController.transform.rotation,
|
||||
targetRotation,
|
||||
rotationLerpSpeed * Time.deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Look
|
||||
|
||||
public float rotationSyncInterval = 0.15f;
|
||||
public float minRotationChange = 10f;
|
||||
|
||||
private Vector3 _rotationInput = Vector3.zero;
|
||||
private float rotationSyncTimer;
|
||||
private Vector3 lastSyncedFacing;
|
||||
private bool isRotating = false;
|
||||
|
||||
[Tooltip("视角旋转敏感度")] public Vector2 sensitivity = new Vector2(0.015f, 0.015f);
|
||||
|
||||
private void UpdatePlayerRotation(Vector2 lookValue)
|
||||
{
|
||||
// Look
|
||||
Vector2 lookInput = lookValue * sensitivity;
|
||||
|
||||
// 处理水平旋转 (Yaw)
|
||||
if (lookInput.x != 0.0f)
|
||||
{
|
||||
_rotationInput.y += lookInput.x;
|
||||
isRotating = true;
|
||||
}
|
||||
|
||||
// 应用旋转到角色和相机
|
||||
if (_rotationInput != Vector3.zero)
|
||||
{
|
||||
characterController.transform.rotation *= Quaternion.Euler(0, _rotationInput.y, 0);
|
||||
_rotationInput = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查朝向同步
|
||||
private void CheckRotationSync()
|
||||
{
|
||||
if (!IsSelf) return;
|
||||
rotationSyncTimer += Time.deltaTime;
|
||||
if (rotationSyncTimer >= rotationSyncInterval)
|
||||
{
|
||||
float angleChange = Vector3.Angle(transform.forward, lastSyncedFacing);
|
||||
|
||||
// 修改:即使在旋转中也定期同步朝向,避免累积误差
|
||||
if (angleChange >= minRotationChange || isRotating)
|
||||
{
|
||||
SendLookMessage();
|
||||
lastSyncedFacing = transform.forward;
|
||||
rotationSyncTimer = 0f;
|
||||
isRotating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36fb267f0f5149caa23ac1b6cf005067
|
||||
timeCreated: 1757164955
|
||||
@@ -1,108 +0,0 @@
|
||||
using ECM2.Examples.FirstPerson;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class CharacterLookComponent : Entity
|
||||
{
|
||||
// private UnitUnityComponent _UnitUnityComponent;
|
||||
public FirstPersonCharacter FirstPerson { get; set; }
|
||||
private float lookXRot;
|
||||
private float lookYRot;
|
||||
private Vector2 _moveInput;
|
||||
|
||||
public float MouseSensitivity = 0.1f;
|
||||
[Space(15f)] public bool invertLook = true;
|
||||
|
||||
public float minPitch = -60f;
|
||||
|
||||
public float maxPitch = 60f;
|
||||
|
||||
|
||||
private InputComponent _inputComponent;
|
||||
private Quaternion lastRotation;
|
||||
public MapUnit MapUnit;
|
||||
|
||||
#region System
|
||||
|
||||
public class LookComponentDestroySystem : DestroySystem<CharacterLookComponent>
|
||||
{
|
||||
protected override void Destroy(CharacterLookComponent self)
|
||||
{
|
||||
self.FirstPerson = null;
|
||||
// var mapUnit = self.Parent as MapUnit;
|
||||
|
||||
self._inputComponent = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class LookComponentAwakeSystem : AwakeSystem<CharacterLookComponent>
|
||||
{
|
||||
protected override void Awake(CharacterLookComponent self)
|
||||
{
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
self.MapUnit = mapUnit;
|
||||
var unitUnityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self.FirstPerson = unitUnityComponent.FirstPerson;
|
||||
self._inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
}
|
||||
}
|
||||
|
||||
public class LookComponentUpdateSystem : UpdateSystem<CharacterLookComponent>
|
||||
{
|
||||
protected override void Update(CharacterLookComponent self)
|
||||
{
|
||||
self.UpdateLookInput();
|
||||
}
|
||||
}
|
||||
|
||||
// public class LookComponentLateUpdateSystem : LateUpdateSystem<CharacterLookComponent>
|
||||
// {
|
||||
// protected override void LateUpdate(CharacterLookComponent self)
|
||||
// {
|
||||
// self.UpdateLookInput();
|
||||
// }
|
||||
// }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void UpdateLookInput()
|
||||
{
|
||||
|
||||
// TPPLookTarget.position = base.transform.position;
|
||||
// if (CameraView.Value == CameraViewType.TPP)
|
||||
// {
|
||||
// lookXRot -= MouseInput.Value.y;
|
||||
// lookXRot = Mathf.Clamp(lookXRot, -25f, 55f);
|
||||
// lookYRot += MouseInput.Value.x;
|
||||
// lookYRot = Mathf.Repeat(lookYRot, 360f);
|
||||
// TPPLookTarget.localEulerAngles = new Vector3(lookXRot, lookYRot, 0f);
|
||||
// }
|
||||
// else if (CameraView.Value == CameraViewType.FPP)
|
||||
{
|
||||
// if (_IsInVehicle && PlayerState.Value == State.vehicle)
|
||||
// {
|
||||
// lookXRot -= MouseInput.Value.y;
|
||||
// lookXRot = Mathf.Clamp(lookXRot, VehicleLookXMinMax.x, VehicleLookXMinMax.y);
|
||||
// lookYRot += MouseInput.Value.x;
|
||||
// lookYRot = Mathf.Clamp(lookYRot, VehicleLookYMinMax.x, VehicleLookYMinMax.y);
|
||||
// VehicleLookTargetParent.localEulerAngles = new Vector3(lookXRot, lookYRot, 0f);
|
||||
// _character.CameraPitch = 0f;
|
||||
// }
|
||||
// else
|
||||
{
|
||||
Vector2 value = _inputComponent.GetLookInput();
|
||||
FirstPerson.AddControlYawInput(value.x * (float)MouseSensitivity);
|
||||
FirstPerson.AddControlPitchInput((invertLook ? (0f - value.y) : value.y) * (float)MouseSensitivity,
|
||||
minPitch, maxPitch);
|
||||
// lookXRot = base.transform.eulerAngles.x;
|
||||
// lookYRot = base.transform.eulerAngles.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 316d2e71f8b3473e961ac86ce4568704
|
||||
timeCreated: 1765283815
|
||||
@@ -1,214 +0,0 @@
|
||||
using ECM2;
|
||||
using ECM2.Examples.FirstPerson;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class CharacterMovementComponent : Entity
|
||||
{
|
||||
public bool IsSelf;
|
||||
public bool Run;
|
||||
|
||||
private Vector2 _moveInput;
|
||||
public MapUnit MapUnit;
|
||||
|
||||
private FirstPersonCharacter _Character;
|
||||
private Quaternion lastRotation;
|
||||
|
||||
#region System
|
||||
|
||||
public class MovementComponentDestroySystem : DestroySystem<CharacterMovementComponent>
|
||||
{
|
||||
protected override void Destroy(CharacterMovementComponent self)
|
||||
{
|
||||
// self.characterController = null;
|
||||
self.IsSelf = false;
|
||||
self.Run = false;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
if (inputComponent != null)
|
||||
{
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerCanceled;
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerPerformed;
|
||||
|
||||
inputComponent.OnPlayerValueCanceled -= self.OnPlayerValueCanceled;
|
||||
inputComponent.OnPlayerValuePerformed -= self.OnPlayerValuePerformed;
|
||||
}
|
||||
}
|
||||
|
||||
// self.PlayerAsset = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class MovementComponentAwakeSystem : AwakeSystem<CharacterMovementComponent>
|
||||
{
|
||||
protected override void Awake(CharacterMovementComponent self)
|
||||
{
|
||||
var unitUnityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self._Character = unitUnityComponent.FirstPerson;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
self.MapUnit = mapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
self.IsSelf = true;
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerCanceled;
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerPerformed;
|
||||
|
||||
inputComponent.OnPlayerValueCanceled += self.OnPlayerValueCanceled;
|
||||
inputComponent.OnPlayerValuePerformed += self.OnPlayerValuePerformed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MovementComponentUpdateSystem : UpdateSystem<CharacterMovementComponent>
|
||||
{
|
||||
protected override void Update(CharacterMovementComponent self)
|
||||
{
|
||||
self.UpdateGrounded();
|
||||
self.UpdateWater();
|
||||
self.ProcessMoveStates();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Input
|
||||
|
||||
private void OnPlayerPerformed(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Run = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerCanceled(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Run = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValueCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
var name = context.action.name;
|
||||
if (name == InputDef.Player.Move)
|
||||
{
|
||||
// var v2 = context.ReadValue<Vector2>();
|
||||
_moveInput = Vector2.zero;
|
||||
// SendMoveMessage(v2, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValuePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
// var mapUnit = Parent as MapUnit;
|
||||
// Log.Info($"OnPlayerValuePerformed IsSelf={mapUnit.IsSelf()} id={mapUnit.Id}");
|
||||
var name = context.action.name;
|
||||
if (name == InputDef.Player.Move)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
_moveInput = v2;
|
||||
// SendMoveMessage(v2, false);
|
||||
}
|
||||
else if (name == InputDef.Player.Look)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
// UpdatePlayerRotation(v2);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Move
|
||||
|
||||
private void UpdateGrounded()
|
||||
{
|
||||
MapUnit.IsGrounded = _Character.IsGrounded();
|
||||
MapUnit.Speed = _Character.velocity.magnitude;
|
||||
|
||||
|
||||
Quaternion rotation = _Character.transform.rotation;
|
||||
|
||||
// 计算当前帧与上一帧的旋转差异
|
||||
Quaternion rotationDelta = rotation * Quaternion.Inverse(lastRotation);
|
||||
|
||||
// 将四元数转换为角度轴表示
|
||||
rotationDelta.ToAngleAxis(out float angle, out Vector3 axis);
|
||||
|
||||
// 确保角度在0-360范围内
|
||||
if (angle > 180f) angle -= 360f;
|
||||
|
||||
// 获取Y轴旋转分量(归一化处理)
|
||||
float yRotation = 0f;
|
||||
if (Mathf.Abs(angle) > 0.001f && Mathf.Abs(axis.y) > 0.1f)
|
||||
{
|
||||
// 计算Y轴方向的旋转角度(考虑旋转轴方向)
|
||||
yRotation = angle * Mathf.Sign(axis.y);
|
||||
}
|
||||
|
||||
float maxTurnSpeed = 180f; // 度/秒
|
||||
// 转换为角速度并归一化到[-1, 1]
|
||||
float angularSpeed = yRotation / Time.deltaTime;
|
||||
float turnValue = Mathf.Clamp(angularSpeed / maxTurnSpeed, -1f, 1f);
|
||||
|
||||
|
||||
MapUnit.RotationSpeed = turnValue;
|
||||
|
||||
lastRotation = rotation;
|
||||
}
|
||||
|
||||
private void UpdateWater()
|
||||
{
|
||||
// SceneSettings.Instance.Water.w
|
||||
}
|
||||
|
||||
private void ProcessMoveStates()
|
||||
{
|
||||
// if (CameraView.Value == CameraViewType.TPP)
|
||||
// {
|
||||
// float num = (IsRunPressed.Value ? MovementSpeed.Value : (MovementSpeed.Value * 0.5f));
|
||||
// num = (IsFlyModeEnabled ? (num * (float)FlySpeed) : num);
|
||||
// Vector3 zero = Vector3.zero;
|
||||
// zero += Vector3.right * MovementDirection.Value.x;
|
||||
// zero += Vector3.forward * MovementDirection.Value.y;
|
||||
// zero = zero.relativeTo(_CameraTPPTarget, _Character.GetUpVector());
|
||||
// _Character.RotateTowards(zero, Time.deltaTime * _RotateTPPSpeed);
|
||||
// float value = Vector3.Dot(_Character.GetForwardVector(), zero);
|
||||
// Vector3 vector = _Character.GetForwardVector() * Mathf.Clamp01(value) * num;
|
||||
// if (checkWaterBound)
|
||||
// {
|
||||
// SetMovementDirectionWithRaycastCheck(vector);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _Character.SetMovementDirection(vector);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
{
|
||||
float num2 = Run ? 7 : 5; //(IsRunPressed.Value ? MovementSpeed.Value : (MovementSpeed.Value * 0.5f));
|
||||
// num2 = (IsFlyModeEnabled ? (num2 * (float)FlySpeed) : num2);
|
||||
Vector3 vector2 = _Character.GetRightVector() * _moveInput.x * num2;
|
||||
vector2 += _Character.GetForwardVector() * _moveInput.y * num2;
|
||||
// if (checkWaterBound)
|
||||
// {
|
||||
// SetMovementDirectionWithRaycastCheck(vector2);
|
||||
// }
|
||||
// else
|
||||
{
|
||||
_Character.SetMovementDirection(vector2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f032bbea4a2a4ab099d2f4800670ad48
|
||||
timeCreated: 1765282951
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f63b5a4df9be4d1c839c3c1cc56c1275
|
||||
timeCreated: 1756048419
|
||||
@@ -1,15 +0,0 @@
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
/// <summary>
|
||||
/// 手电筒组件
|
||||
/// </summary>
|
||||
public class UnitFlashlightComponent : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 打开手电筒
|
||||
/// </summary>
|
||||
public bool OpenLight { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f151cee0d5f43ff90c3aa013214b1ea
|
||||
timeCreated: 1756048476
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f655e37e9dd4b5885e127f44e01100d
|
||||
timeCreated: 1756048586
|
||||
@@ -1,11 +0,0 @@
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
/// <summary>
|
||||
/// Unity皮肤组件
|
||||
/// </summary>
|
||||
public class UnitSkinComponent : Entity
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40c5cce71c8443aa82ea4108e72c887b
|
||||
timeCreated: 1756048599
|
||||
@@ -1,22 +0,0 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public struct ChangePosition
|
||||
{
|
||||
public MapUnit MapUnit;
|
||||
public float3 OldPos;
|
||||
}
|
||||
|
||||
public struct ChangeRotation
|
||||
{
|
||||
public MapUnit MapUnit;
|
||||
}
|
||||
|
||||
public struct ChangeState
|
||||
{
|
||||
public MapUnit MapUnit;
|
||||
public MapUnitState State;
|
||||
public string Args;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd2dd8a7207544b19be4b51b2a6ef215
|
||||
timeCreated: 1755915609
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2120457449841468649709d6b193c35
|
||||
timeCreated: 1756821388
|
||||
@@ -1,113 +0,0 @@
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class CharacterAnimatorComponent : Entity
|
||||
{
|
||||
#region 参数定义
|
||||
|
||||
public static readonly int IsSwiming = Animator.StringToHash("Swim");
|
||||
|
||||
public static readonly int ThrowFar = Animator.StringToHash("ThrowFar");
|
||||
|
||||
public static readonly int BoatDriving = Animator.StringToHash("BoatDriving");
|
||||
|
||||
public static readonly int BaitInWater = Animator.StringToHash("BaitInWater");
|
||||
|
||||
public static readonly int HeldRod = Animator.StringToHash("HeldRod");
|
||||
|
||||
public static readonly int RodArming = Animator.StringToHash("RodArming");
|
||||
|
||||
public static readonly int Forward = Animator.StringToHash("Forward");
|
||||
|
||||
public static readonly int Turn = Animator.StringToHash("Turn");
|
||||
|
||||
public static readonly int OnGround = Animator.StringToHash("OnGround");
|
||||
|
||||
public static readonly int RodRight = Animator.StringToHash("rod right");
|
||||
|
||||
public static readonly int RodForward = Animator.StringToHash("rod forward");
|
||||
|
||||
public static readonly int PreciseCast = Animator.StringToHash("Precise Cast");
|
||||
|
||||
public static readonly int PreciseIdle = Animator.StringToHash("Precise Idle");
|
||||
|
||||
|
||||
public static readonly string Torso = "Torso";
|
||||
|
||||
#endregion
|
||||
|
||||
public Animator Animator { get; private set; }
|
||||
public MapUnit MapUnit;
|
||||
|
||||
private bool _isTorsoLayerEnabled;
|
||||
|
||||
#region System
|
||||
|
||||
public class CharacterAnimatorComponentDestroySystem : DestroySystem<CharacterAnimatorComponent>
|
||||
{
|
||||
protected override void Destroy(CharacterAnimatorComponent self)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class CharacterAnimatorComponentAwakeSystem : AwakeSystem<CharacterAnimatorComponent>
|
||||
{
|
||||
protected override void Awake(CharacterAnimatorComponent self)
|
||||
{
|
||||
self.MapUnit = self.Parent as MapUnit;
|
||||
var unitUnityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self.Animator = unitUnityComponent.ModelAsset.Animator;
|
||||
}
|
||||
}
|
||||
|
||||
// public class CharacterAnimatorComponentUpdateSystem : UpdateSystem<CharacterAnimatorComponent>
|
||||
// {
|
||||
// protected override void Update(CharacterAnimatorComponent self)
|
||||
// {
|
||||
// // self.UpdateAnimator();
|
||||
// }
|
||||
// }
|
||||
|
||||
public class CharacterAnimatorComponentLateUpdateSystem : LateUpdateSystem<CharacterAnimatorComponent>
|
||||
{
|
||||
protected override void LateUpdate(CharacterAnimatorComponent self)
|
||||
{
|
||||
self.UpdateAnimator();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void UpdateAnimator()
|
||||
{
|
||||
Animator.SetBool(OnGround, MapUnit.IsGrounded);
|
||||
float value3 = Mathf.Lerp(Animator.GetFloat(Forward), MapUnit.Speed / 5f, Time.deltaTime * 20f);
|
||||
Animator.SetFloat(Forward, value3);
|
||||
|
||||
// 平滑处理
|
||||
// float smoothedTurn = Mathf.SmoothDamp(Animator.GetFloat(Turn),
|
||||
// MapUnit.RotationSpeed,
|
||||
// ref turnSmoothVelocity,
|
||||
// smoothingTime
|
||||
// );
|
||||
|
||||
float smoothedTurn = Mathf.Lerp(Animator.GetFloat(Turn), MapUnit.RotationSpeed, Time.deltaTime * 10f);
|
||||
Animator.SetFloat(Turn, smoothedTurn);
|
||||
|
||||
|
||||
float layerWeight = Animator.GetLayerWeight(Animator.GetLayerIndex(Torso));
|
||||
SetLayerWeight(Torso,
|
||||
Mathf.MoveTowards(layerWeight, _isTorsoLayerEnabled ? 1f : 0f, Time.deltaTime * 3f));
|
||||
}
|
||||
|
||||
public void SetLayerWeight(string layer, float weight)
|
||||
{
|
||||
Animator.SetLayerWeight(Animator.GetLayerIndex(layer), weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c8042507191477295dbdac2c7dd7c59
|
||||
timeCreated: 1765353895
|
||||
@@ -1,74 +0,0 @@
|
||||
using ECM2;
|
||||
using ECM2.Examples.FirstPerson;
|
||||
using Fantasy.Async;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit 对应的unity对象组件
|
||||
/// </summary>
|
||||
public class UnitUnityComponent : Entity
|
||||
{
|
||||
public GameObject GameObject { get; set; }
|
||||
public GameObject ModelGameObject { get; set; }
|
||||
|
||||
public Transform Transform { get; set; }
|
||||
|
||||
public PlayerModelAsset ModelAsset { get; set; }
|
||||
|
||||
public CharacterMovement Character { get; set; }
|
||||
public FirstPersonCharacter FirstPerson { get; set; }
|
||||
|
||||
public PlayerRootAsset RootAsset { get; set; }
|
||||
|
||||
#region System
|
||||
|
||||
public class UnitUnityComponentDestroySystem : DestroySystem<UnitUnityComponent>
|
||||
{
|
||||
protected override void Destroy(UnitUnityComponent self)
|
||||
{
|
||||
if (self.GameObject != null)
|
||||
{
|
||||
Object.Destroy(self.GameObject);
|
||||
}
|
||||
|
||||
self.ModelAsset = null;
|
||||
self.GameObject = null;
|
||||
self.Transform = null;
|
||||
self.Character = null;
|
||||
self.FirstPerson = null;
|
||||
self.RootAsset = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public async FTask InitUnityObject()
|
||||
{
|
||||
var gameObject = PrefabsHelper.CreatePlayer(SceneSettings.Instance.Node);
|
||||
GameObject = gameObject;
|
||||
Transform = gameObject.transform;
|
||||
Transform.localPosition = new Vector3(484, 1, 422);
|
||||
Parent.GetOrAddComponent<FlashlightComponent>();
|
||||
Character = gameObject.GetComponent<CharacterMovement>();
|
||||
FirstPerson = gameObject.GetComponent<FirstPersonCharacter>();
|
||||
RootAsset = gameObject.GetComponent<PlayerRootAsset>();
|
||||
// Parent.GetOrAddComponent<CharacterControllerComponent>();
|
||||
|
||||
var modelObject = PrefabsHelper.CreatePlayer(RootAsset.Root, "Human_Male");
|
||||
modelObject.transform.localPosition = Vector3.zero;
|
||||
ModelGameObject = modelObject;
|
||||
ModelAsset = modelObject.GetComponent<PlayerModelAsset>();
|
||||
|
||||
|
||||
Parent.GetOrAddComponent<CharacterMovementComponent>();
|
||||
Parent.GetOrAddComponent<CharacterLookComponent>();
|
||||
Parent.GetOrAddComponent<CharacterAnimatorComponent>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d2c42a4bc1347cebc390147a1a95c54
|
||||
timeCreated: 1755921030
|
||||
3
Assets/Scripts/Test.meta
Normal file
3
Assets/Scripts/Test.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d71eb3d89064cc4aab3317e49dc3979
|
||||
timeCreated: 1772097895
|
||||
24
Assets/Scripts/Test/BobberTest.cs
Normal file
24
Assets/Scripts/Test/BobberTest.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using NBF;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class BobberTest : MonoBehaviour
|
||||
{
|
||||
public Rigidbody rb;
|
||||
public FLine line;
|
||||
|
||||
public float lineLength = 1f;
|
||||
public float floatLength = 0.5f;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
line.InitTest(rb);
|
||||
//有浮漂
|
||||
line.Lure.SetJointDistance(floatLength);
|
||||
line.Bobber.SetJointDistance(lineLength - floatLength);
|
||||
line.SetObiRopeStretch(lineLength - floatLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Test/BobberTest.cs.meta
Normal file
3
Assets/Scripts/Test/BobberTest.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e21f6b9b3c2483e92fdf2f3dfdcce62
|
||||
timeCreated: 1772097978
|
||||
16
Assets/Scripts/Test/FlatWaterHeightProvider.cs
Normal file
16
Assets/Scripts/Test/FlatWaterHeightProvider.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
public interface IWaterHeightProvider
|
||||
{
|
||||
/// <summary>返回 worldPos 位置的水面高度(Y)</summary>
|
||||
float GetWaterHeight(Vector3 worldPos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最简单的水面:固定平面(适合先跑通逻辑)
|
||||
/// </summary>
|
||||
public class FlatWaterHeightProvider : MonoBehaviour, IWaterHeightProvider
|
||||
{
|
||||
public float waterY = 0f;
|
||||
public float GetWaterHeight(Vector3 worldPos) => waterY;
|
||||
}
|
||||
2
Assets/Scripts/Test/FlatWaterHeightProvider.cs.meta
Normal file
2
Assets/Scripts/Test/FlatWaterHeightProvider.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1300e9b5a5c347408708087176324c0
|
||||
370
Assets/Scripts/Test/FloatBobberController.cs
Normal file
370
Assets/Scripts/Test/FloatBobberController.cs
Normal file
@@ -0,0 +1,370 @@
|
||||
// using UnityEngine;
|
||||
//
|
||||
// [DisallowMultipleComponent]
|
||||
// public class FloatBobberController : MonoBehaviour
|
||||
// {
|
||||
// public enum FloatState
|
||||
// {
|
||||
// FreePhysics, // 正常物理
|
||||
// Standing, // 站漂(可选:更“稳”的物理态)
|
||||
// Laying, // 躺漂(浮力过大/出水过多)
|
||||
// AnimBite // 漂相动画接管:黑漂/顿漂/移漂/顶漂
|
||||
// }
|
||||
//
|
||||
// public enum BiteType
|
||||
// {
|
||||
// Black, // 黑漂:快速下沉
|
||||
// Dip, // 顿漂:下压一下回弹
|
||||
// Move, // 移漂:水平拖动
|
||||
// Lift // 顶漂:上顶(上浮)
|
||||
// }
|
||||
//
|
||||
// [Header("Refs")]
|
||||
// public Rigidbody rb;
|
||||
// public ConfigurableJoint joint; // 浮漂与鱼钩端连接的 joint
|
||||
// public MonoBehaviour waterProviderMB; // 拖一个实现 IWaterHeightProvider 的组件(如 FlatWaterHeightProvider / KWS适配器)
|
||||
// private IWaterHeightProvider water;
|
||||
//
|
||||
// [Header("Buoyancy")]
|
||||
// [Tooltip("浮漂的有效高度(决定淹没比例计算)")]
|
||||
// public float floatHeight = 0.18f;
|
||||
// [Tooltip("浮力系数(越大越容易浮起)")]
|
||||
// public float buoyancy = 18f;
|
||||
// [Tooltip("水中阻尼(抑制乱抖/失控)")]
|
||||
// public float waterDrag = 2.0f;
|
||||
// [Tooltip("水中角阻尼")]
|
||||
// public float waterAngularDrag = 2.0f;
|
||||
//
|
||||
// [Header("Auto Lay (躺漂判定)")]
|
||||
// [Tooltip("出水比例超过这个值(0~1),且浮力明显大于重力时,进入躺漂")]
|
||||
// [Range(0f, 1f)] public float tooMuchOutOfWater01 = 0.55f;
|
||||
// [Tooltip("浮力/重力比超过该值,认为浮力过大(更容易躺漂)")]
|
||||
// public float buoyancyOverGravityToLay = 1.15f;
|
||||
// [Tooltip("躺漂时目标倾角(度)")]
|
||||
// public float layTiltAngle = 75f;
|
||||
// [Tooltip("躺漂倾斜速度")]
|
||||
// public float layTiltSpeed = 6f;
|
||||
//
|
||||
// [Header("Joint Drive (用于动画接管)")]
|
||||
// public float animDriveSpring = 1200f;
|
||||
// public float animDriveDamper = 120f;
|
||||
// public float animMaxForce = 10000f;
|
||||
//
|
||||
// [Header("Bite Animation Settings")]
|
||||
// public BiteAnim black = new BiteAnim
|
||||
// {
|
||||
// duration = 0.35f,
|
||||
// verticalOffset = -0.14f,
|
||||
// curve = AnimationCurve.EaseInOut(0, 0, 1, 1)
|
||||
// };
|
||||
//
|
||||
// public BiteAnim dip = new BiteAnim
|
||||
// {
|
||||
// duration = 0.55f,
|
||||
// verticalOffset = -0.08f,
|
||||
// curve = new AnimationCurve(
|
||||
// new Keyframe(0, 0),
|
||||
// new Keyframe(0.25f, 1f),
|
||||
// new Keyframe(0.6f, 0.2f),
|
||||
// new Keyframe(1f, 0)
|
||||
// )
|
||||
// };
|
||||
//
|
||||
// public BiteAnim lift = new BiteAnim
|
||||
// {
|
||||
// duration = 0.6f,
|
||||
// verticalOffset = +0.06f,
|
||||
// curve = new AnimationCurve(
|
||||
// new Keyframe(0, 0),
|
||||
// new Keyframe(0.3f, 1f),
|
||||
// new Keyframe(1f, 0)
|
||||
// )
|
||||
// };
|
||||
//
|
||||
// public BiteAnim move = new BiteAnim
|
||||
// {
|
||||
// duration = 0.9f,
|
||||
// horizontalOffset = 0.18f,
|
||||
// curve = AnimationCurve.EaseInOut(0, 0, 1, 1)
|
||||
// };
|
||||
//
|
||||
// [System.Serializable]
|
||||
// public struct BiteAnim
|
||||
// {
|
||||
// public float duration;
|
||||
// public AnimationCurve curve;
|
||||
// [Tooltip("相对水面的竖直偏移幅度(m),负数=下沉,正数=上顶")]
|
||||
// public float verticalOffset;
|
||||
// [Tooltip("水平偏移幅度(m),用于移漂(沿 forward 或指定方向)")]
|
||||
// public float horizontalOffset;
|
||||
// }
|
||||
//
|
||||
// [Header("Runtime")]
|
||||
// public FloatState state = FloatState.FreePhysics;
|
||||
//
|
||||
// // 内部:动画接管
|
||||
// private BiteType currentBite;
|
||||
// private float biteT;
|
||||
// private float biteDuration;
|
||||
// private BiteAnim biteAnim;
|
||||
// private Vector3 biteDirWorld; // 移漂方向
|
||||
// private Vector3 jointBaseTargetPos;
|
||||
// private bool jointHadTarget;
|
||||
//
|
||||
// private void Reset()
|
||||
// {
|
||||
// rb = GetComponent<Rigidbody>();
|
||||
// joint = GetComponent<ConfigurableJoint>();
|
||||
// }
|
||||
//
|
||||
// private void Awake()
|
||||
// {
|
||||
// if (!rb) rb = GetComponent<Rigidbody>();
|
||||
// if (!joint) joint = GetComponent<ConfigurableJoint>();
|
||||
//
|
||||
// water = waterProviderMB as IWaterHeightProvider;
|
||||
// if (water == null && waterProviderMB != null)
|
||||
// water = waterProviderMB.GetComponent<IWaterHeightProvider>();
|
||||
//
|
||||
// // joint 初始化建议(确保 targetPosition 驱动生效)
|
||||
// if (joint)
|
||||
// {
|
||||
// joint.configuredInWorldSpace = false; // targetPosition 在 joint 的本地坐标系更稳定
|
||||
// joint.rotationDriveMode = RotationDriveMode.Slerp;
|
||||
//
|
||||
// // 建议锁住角度,避免动画接管时乱拧;如果你需要漂转向可放开
|
||||
// joint.angularXMotion = ConfigurableJointMotion.Locked;
|
||||
// joint.angularYMotion = ConfigurableJointMotion.Locked;
|
||||
// joint.angularZMotion = ConfigurableJointMotion.Locked;
|
||||
//
|
||||
// // 位置建议:X/Z 限制,Y 可自由(看你钓组结构)
|
||||
// // 这里不强制修改,你项目里如果已经配好了就别动
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void FixedUpdate()
|
||||
// {
|
||||
// if (water == null)
|
||||
// {
|
||||
// // 没水面采样就只能纯物理
|
||||
// state = FloatState.FreePhysics;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// Vector3 pos = rb.position;
|
||||
// float waterY = water.GetWaterHeight(pos);
|
||||
//
|
||||
// // 计算淹没比例:以浮漂中心为基准,上下 floatHeight/2
|
||||
// float topY = pos.y + floatHeight * 0.5f;
|
||||
// float bottomY = pos.y - floatHeight * 0.5f;
|
||||
//
|
||||
// float submerged01 = 0f;
|
||||
// if (waterY <= bottomY) submerged01 = 0f;
|
||||
// else if (waterY >= topY) submerged01 = 1f;
|
||||
// else submerged01 = Mathf.InverseLerp(bottomY, topY, waterY);
|
||||
//
|
||||
// float outOfWater01 = 1f - submerged01;
|
||||
//
|
||||
// // 基础浮力 & 阻尼(只在水中起作用)
|
||||
// ApplyBuoyancy(submerged01, waterY);
|
||||
//
|
||||
// // 躺漂判定(只在非动画接管时)
|
||||
// if (state != FloatState.AnimBite)
|
||||
// {
|
||||
// bool shouldLay = ShouldLay(outOfWater01, submerged01);
|
||||
// if (shouldLay)
|
||||
// state = FloatState.Laying;
|
||||
// else
|
||||
// state = FloatState.FreePhysics; // 你也可以在这里细分 Standing
|
||||
// }
|
||||
//
|
||||
// // 状态行为
|
||||
// switch (state)
|
||||
// {
|
||||
// case FloatState.Laying:
|
||||
// DoLay(waterY);
|
||||
// break;
|
||||
//
|
||||
// case FloatState.AnimBite:
|
||||
// DoBiteAnim(waterY);
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// // 正常物理时恢复 joint drive(避免被动画参数影响)
|
||||
// RestoreJointDriveIfNeeded();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void ApplyBuoyancy(float submerged01, float waterY)
|
||||
// {
|
||||
// // 水中阻尼:淹没越多阻尼越强
|
||||
// rb.linearDamping = Mathf.Lerp(rb.linearDamping, submerged01 > 0 ? waterDrag : 0f, 0.25f);
|
||||
// rb.angularDamping = Mathf.Lerp(rb.angularDamping, submerged01 > 0 ? waterAngularDrag : 0.05f, 0.25f);
|
||||
//
|
||||
// if (submerged01 <= 0f) return;
|
||||
//
|
||||
// // 浮力:与淹没比例近似线性(你也可以换成平方让“接近全淹没时更强”)
|
||||
// float g = Physics.gravity.magnitude;
|
||||
// float buoyForce = buoyancy * submerged01;
|
||||
//
|
||||
// // 让浮力作用点略低于中心,产生一点“站漂”稳定性(可选)
|
||||
// Vector3 forcePoint = rb.worldCenterOfMass + Vector3.down * (floatHeight * 0.15f);
|
||||
//
|
||||
// rb.AddForceAtPosition(Vector3.up * buoyForce, forcePoint, ForceMode.Force);
|
||||
//
|
||||
// // 额外:把浮漂轻轻拉向水面(避免小抖导致上下乱跳)
|
||||
// float surfacePull = 6f * submerged01;
|
||||
// float yError = waterY - rb.position.y;
|
||||
// rb.AddForce(Vector3.up * (yError * surfacePull), ForceMode.Force);
|
||||
// }
|
||||
//
|
||||
// private bool ShouldLay(float outOfWater01, float submerged01)
|
||||
// {
|
||||
// if (submerged01 <= 0f) return false;
|
||||
//
|
||||
// // “浮力/重力”粗判:浮力系数与质量、g相关
|
||||
// float gravityForce = rb.mass * Physics.gravity.magnitude;
|
||||
// // 这里的 buoyancy 是 ForceMode.Force 下的“牛顿”,所以直接比值即可
|
||||
// float buoyForceAtFull = buoyancy; // submerged=1 时
|
||||
// float ratio = buoyForceAtFull / Mathf.Max(0.0001f, gravityForce);
|
||||
//
|
||||
// return (outOfWater01 >= tooMuchOutOfWater01) && (ratio >= buoyancyOverGravityToLay);
|
||||
// }
|
||||
//
|
||||
// private void DoLay(float waterY)
|
||||
// {
|
||||
// // 躺漂:把浮漂慢慢倾斜到 layTiltAngle,同时让它更贴近水面
|
||||
// Quaternion targetRot = Quaternion.AngleAxis(layTiltAngle, transform.right) * Quaternion.LookRotation(transform.forward, Vector3.up);
|
||||
// rb.MoveRotation(Quaternion.Slerp(rb.rotation, targetRot, layTiltSpeed * Time.fixedDeltaTime));
|
||||
//
|
||||
// // 贴近水面一点(不要完全锁死,保持自然)
|
||||
// float targetY = waterY + floatHeight * 0.15f;
|
||||
// Vector3 p = rb.position;
|
||||
// p.y = Mathf.Lerp(p.y, targetY, 3f * Time.fixedDeltaTime);
|
||||
// rb.MovePosition(p);
|
||||
//
|
||||
// RestoreJointDriveIfNeeded();
|
||||
// }
|
||||
//
|
||||
// private void DoBiteAnim(float waterY)
|
||||
// {
|
||||
// biteT += Time.fixedDeltaTime;
|
||||
// float t01 = (biteDuration <= 0.0001f) ? 1f : Mathf.Clamp01(biteT / biteDuration);
|
||||
// float k = biteAnim.curve != null ? biteAnim.curve.Evaluate(t01) : t01;
|
||||
//
|
||||
// // 目标偏移:相对水面
|
||||
// float yOff = biteAnim.verticalOffset * k;
|
||||
// float xzOff = biteAnim.horizontalOffset * k;
|
||||
//
|
||||
// // 用 joint.targetPosition 驱动:更像“鱼线/钓组拉着漂走/压漂”
|
||||
// if (joint)
|
||||
// {
|
||||
// EnsureJointDriveForAnim();
|
||||
//
|
||||
// // joint.targetPosition 是在 joint space(本地)
|
||||
// // 这里做一个“基准 targetPosition + 偏移”,基准取进入动画时的 targetPosition
|
||||
// Vector3 target = jointBaseTargetPos;
|
||||
//
|
||||
// // 竖直:沿 joint 的 local Y
|
||||
// target += Vector3.up * yOff;
|
||||
//
|
||||
// // 移漂:我们用世界方向投到 joint 的 local XZ(近似)
|
||||
// if (currentBite == BiteType.Move && xzOff != 0f)
|
||||
// {
|
||||
// Vector3 worldOffset = biteDirWorld.normalized * xzOff;
|
||||
// Vector3 localOffset = transform.InverseTransformVector(worldOffset);
|
||||
// target += new Vector3(localOffset.x, 0f, localOffset.z);
|
||||
// }
|
||||
//
|
||||
// joint.targetPosition = target;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 没 joint 就退化:用 MovePosition 做受控位移(稳定但不如 joint 自然)
|
||||
// Vector3 p = rb.position;
|
||||
// p.y = Mathf.Lerp(p.y, waterY + yOff, 12f * Time.fixedDeltaTime);
|
||||
// if (currentBite == BiteType.Move && xzOff != 0f)
|
||||
// p += biteDirWorld.normalized * (xzOff * 0.2f); // 轻推
|
||||
// rb.MovePosition(p);
|
||||
// }
|
||||
//
|
||||
// // 动画结束,回到物理
|
||||
// if (t01 >= 1f)
|
||||
// {
|
||||
// state = FloatState.FreePhysics;
|
||||
// RestoreJointDriveIfNeeded();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void EnsureJointDriveForAnim()
|
||||
// {
|
||||
// if (!joint) return;
|
||||
//
|
||||
// if (!jointHadTarget)
|
||||
// {
|
||||
// jointHadTarget = true;
|
||||
// jointBaseTargetPos = joint.targetPosition;
|
||||
// }
|
||||
//
|
||||
// // 只设置一次也行,这里每次保证一致
|
||||
// JointDrive d = new JointDrive
|
||||
// {
|
||||
// positionSpring = animDriveSpring,
|
||||
// positionDamper = animDriveDamper,
|
||||
// maximumForce = animMaxForce
|
||||
// };
|
||||
//
|
||||
// joint.xDrive = d;
|
||||
// joint.yDrive = d;
|
||||
// joint.zDrive = d;
|
||||
// }
|
||||
//
|
||||
// private void RestoreJointDriveIfNeeded()
|
||||
// {
|
||||
// // 退出动画时恢复基准 target(避免残留偏移)
|
||||
// if (!joint) return;
|
||||
// if (!jointHadTarget) return;
|
||||
//
|
||||
// // 慢慢回到基准 targetPosition(更平滑)
|
||||
// joint.targetPosition = Vector3.Lerp(joint.targetPosition, jointBaseTargetPos, 8f * Time.fixedDeltaTime);
|
||||
//
|
||||
// // 当接近后释放
|
||||
// if ((joint.targetPosition - jointBaseTargetPos).sqrMagnitude < 0.000001f)
|
||||
// {
|
||||
// joint.targetPosition = jointBaseTargetPos;
|
||||
// jointHadTarget = false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 外部触发漂相(鱼咬钩/流水/风/玩家提竿前的反馈等)
|
||||
// /// </summary>
|
||||
// public void PlayBite(BiteType type, Vector3? moveDirWorld = null)
|
||||
// {
|
||||
// currentBite = type;
|
||||
// biteT = 0f;
|
||||
//
|
||||
// biteAnim = type switch
|
||||
// {
|
||||
// BiteType.Black => black,
|
||||
// BiteType.Dip => dip,
|
||||
// BiteType.Move => move,
|
||||
// BiteType.Lift => lift,
|
||||
// _ => black
|
||||
// };
|
||||
//
|
||||
// biteDuration = Mathf.Max(0.02f, biteAnim.duration);
|
||||
// biteDirWorld = moveDirWorld ?? transform.forward;
|
||||
//
|
||||
// // 进入动画接管
|
||||
// state = FloatState.AnimBite;
|
||||
//
|
||||
// // 记录进入动画时 joint 的基准 target
|
||||
// if (joint)
|
||||
// {
|
||||
// jointBaseTargetPos = joint.targetPosition;
|
||||
// jointHadTarget = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
2
Assets/Scripts/Test/FloatBobberController.cs.meta
Normal file
2
Assets/Scripts/Test/FloatBobberController.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c9bb50ca0b0b5547937d3ce82577fad
|
||||
Reference in New Issue
Block a user