导入角色动画,和增加角色控制
This commit is contained in:
123
Assets/Scripts/BobberBuoyancy.cs
Normal file
123
Assets/Scripts/BobberBuoyancy.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class BobberBuoyancy : MonoBehaviour
|
||||
{
|
||||
[Header("Water")]
|
||||
public float waterLevel = 0f; // 水面是 0
|
||||
public Vector3 waterFlow = Vector3.zero;
|
||||
|
||||
[Header("Bobber Size (origin at bottom)")]
|
||||
public float bobberHeight = 0.18f; // 浮漂总高度(底部原点 → 顶部)
|
||||
|
||||
[Header("Buoyancy")]
|
||||
public float maxBuoyancy = 12f; // 完全浸没浮力
|
||||
public float buoyancyMultiplier = 1.0f;
|
||||
public float waterDrag = 0.7f;
|
||||
public float waterAngularDrag = 0.4f;
|
||||
|
||||
[Header("Vertical Damping(控制“慢慢上浮”,避免弹跳)")]
|
||||
public float verticalDamping = 4.0f; // 数值越大,上浮越慢、越不弹
|
||||
|
||||
[Header("Upright")]
|
||||
public float uprightStrength = 8f; // 站漂恢复力
|
||||
public float uprightDamping = 1.2f;
|
||||
|
||||
[Header("Lay Down (躺漂)")]
|
||||
public float layDownThreshold = 0.15f; // 低于 15% 浸没 → 转入躺漂模式
|
||||
public float layDownUprightMultiplier = 0.2f; // 躺漂时保留多少站立力度(越小越“翘头”)
|
||||
|
||||
private Rigidbody rb;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
rb = GetComponent<Rigidbody>();
|
||||
rb.useGravity = true;
|
||||
|
||||
// 重心稍微靠上,配合 AddForceAtPosition,才能让“底在水里、头上翘”
|
||||
rb.centerOfMass = new Vector3(0, bobberHeight * 0.4f, 0);
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
ApplyBuoyancy();
|
||||
ApplyFlowForce();
|
||||
ApplyOrientationControl();
|
||||
}
|
||||
|
||||
void ApplyBuoyancy()
|
||||
{
|
||||
float bottom = rb.position.y; // 原点就是最底部
|
||||
float depth = waterLevel - bottom; // 浸入深度 = 水面 - 底部
|
||||
|
||||
if (depth <= 0f) return; // 完全在水面上方,无浮力
|
||||
|
||||
// 当前浸没比例
|
||||
float submersionRatio = Mathf.Clamp01(depth / bobberHeight);
|
||||
|
||||
// 基础浮力(和你之前一致)
|
||||
float baseForce = maxBuoyancy * submersionRatio * buoyancyMultiplier;
|
||||
|
||||
// ⭐ 竖直速度(用你原来习惯的 linearVelocity)
|
||||
float vy = rb.linearVelocity.y;
|
||||
|
||||
// ⭐ 阻尼项:速度越快,反向力越大
|
||||
// 下沉很快 → 给一个向上的阻尼(减缓下沉)
|
||||
// 向上很快 → 给一个向下的阻尼(防止弹出水面)
|
||||
float damping = -vy * verticalDamping;
|
||||
|
||||
// 总的向上力:基础浮力 + 阻尼修正
|
||||
float totalUpForce = baseForce + damping;
|
||||
|
||||
// 物理上浮力不能把它“往下按”,所以最少为 0
|
||||
if (totalUpForce < 0f) totalUpForce = 0f;
|
||||
|
||||
// ⭐ 浮力作用点 = 浸没体积中心(不动,保持你之前的设计)
|
||||
float clampedDepth = Mathf.Clamp(depth, 0, bobberHeight);
|
||||
float centerY = bottom + clampedDepth * 0.5f;
|
||||
Vector3 buoyancyPoint = new Vector3(rb.position.x, centerY, rb.position.z);
|
||||
|
||||
rb.AddForceAtPosition(Vector3.up * totalUpForce, buoyancyPoint, ForceMode.Acceleration);
|
||||
|
||||
// 水中阻力(保留原逻辑)
|
||||
rb.AddForce(-rb.linearVelocity * waterDrag, ForceMode.Acceleration);
|
||||
rb.AddTorque(-rb.angularVelocity * waterAngularDrag, ForceMode.Acceleration);
|
||||
}
|
||||
|
||||
void ApplyFlowForce()
|
||||
{
|
||||
if (waterFlow.sqrMagnitude <= 0.0001f) return;
|
||||
rb.AddForce((waterFlow - rb.linearVelocity) * 0.3f, ForceMode.Acceleration);
|
||||
}
|
||||
|
||||
void ApplyOrientationControl()
|
||||
{
|
||||
float bottom = rb.position.y;
|
||||
float depth = waterLevel - bottom;
|
||||
float submersionRatio = Mathf.Clamp01(depth / bobberHeight);
|
||||
|
||||
Vector3 up = transform.up;
|
||||
Vector3 worldUp = Vector3.up;
|
||||
|
||||
if (submersionRatio > layDownThreshold)
|
||||
{
|
||||
// 深浸 → 正常站漂
|
||||
Vector3 uprightTorqueVec =
|
||||
Vector3.Cross(up, worldUp) * uprightStrength
|
||||
- rb.angularVelocity * uprightDamping;
|
||||
|
||||
rb.AddTorque(uprightTorqueVec, ForceMode.Acceleration);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 浅浸 → “躺漂”,只保留少量站立力,让它自然斜、头上翘
|
||||
float reduced = uprightStrength * layDownUprightMultiplier;
|
||||
|
||||
Vector3 uprightTorqueVec =
|
||||
Vector3.Cross(up, worldUp) * reduced
|
||||
- rb.angularVelocity * uprightDamping;
|
||||
|
||||
rb.AddTorque(uprightTorqueVec, ForceMode.Acceleration);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/BobberBuoyancy.cs.meta
Normal file
3
Assets/Scripts/BobberBuoyancy.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d2d3d7643d84524b8841fcf62193a04
|
||||
timeCreated: 1764424969
|
||||
@@ -7,14 +7,14 @@ namespace NBF
|
||||
public int Error { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 相机模式切换
|
||||
/// </summary>
|
||||
public struct CameraChangeMode
|
||||
{
|
||||
public CameraShowMode Mode;
|
||||
public MapUnit Unit;
|
||||
}
|
||||
// /// <summary>
|
||||
// /// 相机模式切换
|
||||
// /// </summary>
|
||||
// public struct CameraChangeMode
|
||||
// {
|
||||
// public CameraShowMode Mode;
|
||||
// public MapUnit Unit;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 开始切换场景
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using KWS;
|
||||
using UnityEngine;
|
||||
|
||||
public class SceneSettings : MonoBehaviour
|
||||
{
|
||||
@@ -14,6 +15,7 @@ public class SceneSettings : MonoBehaviour
|
||||
|
||||
public Transform GearNode;
|
||||
|
||||
public KWS_Ocean Water;
|
||||
|
||||
// public ObiLateFixedUpdater obiFixedUpdater;
|
||||
|
||||
|
||||
@@ -1,69 +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
|
||||
{
|
||||
Player,
|
||||
Free,
|
||||
}
|
||||
|
||||
public class CameraComponent : Entity
|
||||
{
|
||||
public CameraShowMode Mode;
|
||||
public Camera Camera;
|
||||
public MapUnit MapUnit;
|
||||
}
|
||||
|
||||
public class CameraChangeModeEvent : AsyncEventSystem<CameraChangeMode>
|
||||
{
|
||||
protected override async FTask Handler(CameraChangeMode self)
|
||||
{
|
||||
var cameraComponent = App.Main.GetComponent<CameraComponent>();
|
||||
cameraComponent.Mode = self.Mode;
|
||||
cameraComponent.MapUnit = self.Unit;
|
||||
cameraComponent.ChangeCameraMode();
|
||||
await FTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CameraComponentSystem
|
||||
{
|
||||
public class CameraComponentAwakeSystem : AwakeSystem<CameraComponent>
|
||||
{
|
||||
protected override void Awake(CameraComponent self)
|
||||
{
|
||||
self.Camera = BaseCamera.Main;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void ChangeCameraMode(this CameraComponent self)
|
||||
{
|
||||
if (self.Mode == CameraShowMode.Player)
|
||||
{
|
||||
if (self.MapUnit != null)
|
||||
{
|
||||
var unityComponent = self.MapUnit.GetComponent<UnitUnityComponent>();
|
||||
if (unityComponent != null)
|
||||
{
|
||||
var root = unityComponent.Asset.FPSCamera;
|
||||
self.Camera.transform.SetParent(root);
|
||||
self.Camera.transform.localPosition = Vector3.zero;
|
||||
self.Camera.transform.localRotation = Quaternion.identity;
|
||||
self.Camera.transform.localScale = Vector3.one;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (self.Mode == CameraShowMode.Free)
|
||||
{
|
||||
self.Camera.transform.SetParent(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
98
Assets/Scripts/Fishing2/Common/CameraComponent.cs
Normal file
98
Assets/Scripts/Fishing2/Common/CameraComponent.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
105
Assets/Scripts/Fishing2/Common/CursorComponent.cs
Normal file
105
Assets/Scripts/Fishing2/Common/CursorComponent.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Event;
|
||||
using NBC;
|
||||
using NBC.Event;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing2/Common/CursorComponent.cs.meta
Normal file
3
Assets/Scripts/Fishing2/Common/CursorComponent.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a04f3272f2604244b8cd9d9923bb35b0
|
||||
timeCreated: 1765374579
|
||||
@@ -57,6 +57,7 @@ namespace NBF.Fishing2
|
||||
var map = App.Main.AddComponent<Map>();
|
||||
map.MapId = mapId;
|
||||
map.RoomCode = roomCode;
|
||||
map.SelfId = Game.SelfId;
|
||||
foreach (var mapUnitInfo in units)
|
||||
{
|
||||
map.CreateMapUnit(mapUnitInfo);
|
||||
@@ -97,20 +98,15 @@ namespace NBF.Fishing2
|
||||
/// <param name="self"></param>
|
||||
public static async FTask LoadAllUnit(this Map self)
|
||||
{
|
||||
MapUnit mapUnit = null;
|
||||
foreach (var (_, unit) in self.Units)
|
||||
{
|
||||
await unit.CreateView();
|
||||
if (unit.IsSelf())
|
||||
{
|
||||
mapUnit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapUnit != null)
|
||||
var cameraComponent = self.Scene.GetComponent<CameraComponent>();
|
||||
if (cameraComponent != null)
|
||||
{
|
||||
await self.Scene.EventComponent.PublishAsync(new CameraChangeMode()
|
||||
{ Mode = CameraShowMode.Player, Unit = mapUnit });
|
||||
cameraComponent.Mode = CameraShowMode.FPP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace NBF.Fishing2
|
||||
{
|
||||
public static class PrefabsHelper
|
||||
{
|
||||
private static GameObject LoadPrefab(string path, Transform parent = null)
|
||||
public static GameObject LoadPrefab(string path, Transform parent = null)
|
||||
{
|
||||
var prefab = Resources.Load<GameObject>(path);
|
||||
return parent == null ? Object.Instantiate(prefab) : Object.Instantiate(prefab, parent);
|
||||
@@ -17,10 +17,11 @@ namespace NBF.Fishing2
|
||||
/// 创建角色预制体
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
/// <param name="modelName"></param>
|
||||
/// <returns></returns>
|
||||
public static GameObject CreatePlayer(Transform parent)
|
||||
public static GameObject CreatePlayer(Transform parent, string modelName = "Player")
|
||||
{
|
||||
var model = LoadPrefab("Prefabs/Player/Human_Male", parent);
|
||||
var model = LoadPrefab($"Prefabs/Player/{modelName}", parent);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -35,7 +36,7 @@ namespace NBF.Fishing2
|
||||
//创建主物体
|
||||
var mainObject = LoadPrefab(config.GetFullModelPath());
|
||||
//创建配件
|
||||
|
||||
|
||||
return mainObject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
@@ -12,6 +13,11 @@ namespace NBF.Fishing2
|
||||
|
||||
public string RoomCode;
|
||||
|
||||
/// <summary>
|
||||
/// 自己的实体id
|
||||
/// </summary>
|
||||
public long SelfId;
|
||||
|
||||
/// <summary>
|
||||
/// 好友房地图
|
||||
/// </summary>
|
||||
@@ -22,20 +28,26 @@ namespace NBF.Fishing2
|
||||
/// </summary>
|
||||
public Dictionary<long, MapUnit> Units = new Dictionary<long, MapUnit>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建地图单位
|
||||
/// 自己的实体
|
||||
/// </summary>
|
||||
public void CreteMapUnit()
|
||||
public MapUnit SelfMapUnit => GetUnit(SelfId);
|
||||
|
||||
|
||||
#region System
|
||||
|
||||
public class MapDestroySystem : DestroySystem<Map>
|
||||
{
|
||||
// //创建自己
|
||||
// var role = Scene.GetComponent<Role>();
|
||||
// var mapUnitInfo = role.GetMapUnitInfo();
|
||||
// CreteMapUnit(mapUnitInfo);
|
||||
//
|
||||
// //创建其他玩家
|
||||
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)
|
||||
{
|
||||
|
||||
13
Assets/Scripts/Fishing2/Mono/CameraAsset.cs
Normal file
13
Assets/Scripts/Fishing2/Mono/CameraAsset.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Cinemachine;
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class CameraAsset : MonoBehaviour
|
||||
{
|
||||
public CinemachineVirtualCamera fppVCam;
|
||||
|
||||
public CinemachineVirtualCamera tppVCam;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing2/Mono/CameraAsset.cs.meta
Normal file
3
Assets/Scripts/Fishing2/Mono/CameraAsset.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dd3e6b2217c463e94e32f15c4ea3c5c
|
||||
timeCreated: 1765306413
|
||||
@@ -18,8 +18,8 @@ namespace NBF.Fishing2
|
||||
{
|
||||
var numericComponent = self.Parent.GetComponent<NumericComponent>();
|
||||
var unityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self._fishingLight = unityComponent.Asset.FishingLight;
|
||||
self.Change(numericComponent[NumericType.Flashlight]);
|
||||
// self._fishingLight = unityComponent.Asset.FishingLight;
|
||||
// self.Change(numericComponent[NumericType.Flashlight]);
|
||||
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Fantasy.Async;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -14,6 +15,19 @@ namespace NBF.Fishing2
|
||||
{
|
||||
public int ConfigId { get; set; } //配置表id
|
||||
|
||||
/// <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
|
||||
@@ -45,10 +59,22 @@ namespace NBF.Fishing2
|
||||
}
|
||||
}
|
||||
|
||||
public uint State { get; set; }
|
||||
public MapUnitState State { get; set; }
|
||||
|
||||
public string StateArgs { get; set; }
|
||||
|
||||
public void ChangeState(uint state, string args)
|
||||
#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 });
|
||||
}
|
||||
@@ -68,16 +94,6 @@ namespace NBF.Fishing2
|
||||
}
|
||||
}
|
||||
|
||||
// public UnitConfig Config()
|
||||
// {
|
||||
// return UnitConfig.Get(ConfigId);
|
||||
// }
|
||||
//
|
||||
// public UnitType UnitType()
|
||||
// {
|
||||
// return Config().Type;
|
||||
// }
|
||||
|
||||
#region View
|
||||
|
||||
public async FTask CreateView()
|
||||
@@ -91,7 +107,7 @@ namespace NBF.Fishing2
|
||||
unitUnity = AddComponent<UnitUnityComponent>();
|
||||
await unitUnity.InitUnityObject();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace NBF.Fishing2
|
||||
public bool IsSelf;
|
||||
public bool Run;
|
||||
public CharacterController characterController;
|
||||
public PlayerAsset PlayerAsset;
|
||||
public PlayerModelAsset PlayerModelAsset;
|
||||
|
||||
public readonly Queue<MoveState> MoveStateQueue = new Queue<MoveState>();
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace NBF.Fishing2
|
||||
}
|
||||
}
|
||||
|
||||
self.PlayerAsset = null;
|
||||
self.PlayerModelAsset = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace NBF.Fishing2
|
||||
protected override void Awake(CharacterControllerComponent self)
|
||||
{
|
||||
var unitUnityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self.PlayerAsset = unitUnityComponent.Asset;
|
||||
self.PlayerModelAsset = unitUnityComponent.ModelAsset;
|
||||
self.characterController = unitUnityComponent.GameObject.GetComponent<CharacterController>();
|
||||
self.lastSyncedFacing = self.characterController.transform.forward;
|
||||
// 初始化目标位置和旋转
|
||||
|
||||
108
Assets/Scripts/Fishing2/Unit/Move/CharacterLookComponent.cs
Normal file
108
Assets/Scripts/Fishing2/Unit/Move/CharacterLookComponent.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 316d2e71f8b3473e961ac86ce4568704
|
||||
timeCreated: 1765283815
|
||||
204
Assets/Scripts/Fishing2/Unit/Move/CharacterMovementComponent.cs
Normal file
204
Assets/Scripts/Fishing2/Unit/Move/CharacterMovementComponent.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
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;
|
||||
float num = Quaternion.Angle(rotation, lastRotation);
|
||||
// float num2 = Vector3.Cross(lastRotation * Vector3.forward, rotation * Vector3.forward).y > 0f
|
||||
// ? 1f
|
||||
// : -1f;
|
||||
bool flag = num > 0f;
|
||||
if (!flag)
|
||||
{
|
||||
MapUnit.RotationSpeed = Mathf.Lerp(MapUnit.RotationSpeed, 0f, 5 * Time.deltaTime);
|
||||
}
|
||||
|
||||
lastRotation = rotation;
|
||||
|
||||
// var TargetMultiplier = 15;
|
||||
|
||||
// float num3 = MapUnit.RotationSpeed < 1f ? TargetMultiplier * 5f : TargetMultiplier;
|
||||
// MapUnit.RotationSpeed += (flag ? 1f : 0f) * num2 * Time.deltaTime *
|
||||
// (Run ? num3 * 0.075f : num3);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f032bbea4a2a4ab099d2f4800670ad48
|
||||
timeCreated: 1765282951
|
||||
@@ -16,7 +16,7 @@ namespace NBF.Fishing2
|
||||
public struct ChangeState
|
||||
{
|
||||
public MapUnit MapUnit;
|
||||
public uint State;
|
||||
public MapUnitState State;
|
||||
public string Args;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
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");
|
||||
|
||||
#endregion
|
||||
|
||||
public Animator Animator { get; private set; }
|
||||
public MapUnit MapUnit;
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
||||
|
||||
#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 value4 = Mathf.Lerp(Animator.GetFloat(Turn), MapUnit.RotationSpeed, Time.deltaTime * 15f);
|
||||
Animator.SetFloat(Turn, Mathf.Clamp(value4, -1f, 1f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c8042507191477295dbdac2c7dd7c59
|
||||
timeCreated: 1765353895
|
||||
3
Assets/Scripts/Fishing2/Unit/Unity/Mono.meta
Normal file
3
Assets/Scripts/Fishing2/Unit/Unity/Mono.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1228e92e0b3744cdb44cd5144a12b241
|
||||
timeCreated: 1765283747
|
||||
153
Assets/Scripts/Fishing2/Unit/Unity/Mono/PlayerIK.cs
Normal file
153
Assets/Scripts/Fishing2/Unit/Unity/Mono/PlayerIK.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerIK : MonoBehaviour
|
||||
{
|
||||
public enum UpdateType
|
||||
{
|
||||
Update = 0,
|
||||
FixedUpdate = 1,
|
||||
LateUpdate = 2,
|
||||
Default = 3
|
||||
}
|
||||
|
||||
public UpdateType UpdateSelected;
|
||||
|
||||
[SerializeField] private Transform _LeftHandTransform;
|
||||
|
||||
private LookAtIK _LookAtIK;
|
||||
|
||||
private AimIK _AimIK;
|
||||
|
||||
private FullBodyBipedIK _FullBodyIK;
|
||||
|
||||
private ArmIK _ArmIK;
|
||||
|
||||
private bool _isLeftHandEnabled;
|
||||
|
||||
private bool _isRightHandEnabled;
|
||||
|
||||
public bool isAimEnabled;
|
||||
|
||||
private bool _isFishingLeftArmEnabled;
|
||||
|
||||
[SerializeField] private float transitionWeightTimeScale = 1f;
|
||||
|
||||
public Transform CurrentTarget => _FullBodyIK.solver.leftHandEffector.target;
|
||||
|
||||
public Transform LeftHandTransform => _LeftHandTransform;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_LookAtIK = GetComponent<LookAtIK>();
|
||||
_AimIK = GetComponent<AimIK>();
|
||||
_FullBodyIK = GetComponent<FullBodyBipedIK>();
|
||||
_ArmIK = GetComponent<ArmIK>();
|
||||
SetAimIK(enabled: false);
|
||||
}
|
||||
|
||||
public void SetBipedIK(bool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetFishingLeftArm(bool enabled)
|
||||
{
|
||||
_isFishingLeftArmEnabled = enabled;
|
||||
}
|
||||
|
||||
public void SetFishingLeftArm(bool enabled, Transform target)
|
||||
{
|
||||
_isFishingLeftArmEnabled = enabled;
|
||||
_ArmIK.solver.arm.target = target;
|
||||
}
|
||||
|
||||
public void SetBipedLeftHandIK(bool enabled, bool instant = false)
|
||||
{
|
||||
_isLeftHandEnabled = enabled;
|
||||
if (instant)
|
||||
{
|
||||
_FullBodyIK.solver.leftArmMapping.weight = (enabled ? 1f : 0f);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBipedRightHandIK(bool enabled, bool instant = false)
|
||||
{
|
||||
_isRightHandEnabled = enabled;
|
||||
if (instant)
|
||||
{
|
||||
_FullBodyIK.solver.rightArmMapping.weight = (enabled ? 1f : 0f);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBipedLeftHandIK(bool enabled, Transform target, bool instant = false)
|
||||
{
|
||||
_isLeftHandEnabled = enabled;
|
||||
_FullBodyIK.solver.leftHandEffector.target = target;
|
||||
if (instant)
|
||||
{
|
||||
_FullBodyIK.solver.leftArmMapping.weight = (enabled ? 1f : 0f);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBipedRightHandIK(bool enabled, Transform target, bool instant = false)
|
||||
{
|
||||
_isRightHandEnabled = enabled;
|
||||
_FullBodyIK.solver.rightHandEffector.target = target;
|
||||
if (instant)
|
||||
{
|
||||
_FullBodyIK.solver.rightArmMapping.weight = (enabled ? 1f : 0f);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAimIK(bool enabled)
|
||||
{
|
||||
isAimEnabled = enabled;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (UpdateSelected == UpdateType.Update)
|
||||
{
|
||||
IKUpdateHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (UpdateSelected == UpdateType.FixedUpdate)
|
||||
{
|
||||
IKUpdateHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (UpdateSelected == UpdateType.LateUpdate)
|
||||
{
|
||||
IKUpdateHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private void IKUpdateHandler()
|
||||
{
|
||||
_AimIK.UpdateSolverExternal();
|
||||
_LookAtIK.UpdateSolverExternal();
|
||||
_FullBodyIK.UpdateSolverExternal();
|
||||
_FullBodyIK.solver.Update();
|
||||
_AimIK.solver.IKPositionWeight = Mathf.MoveTowards(_AimIK.solver.IKPositionWeight, isAimEnabled ? 1f : 0f,
|
||||
Time.deltaTime * transitionWeightTimeScale);
|
||||
_FullBodyIK.solver.leftArmMapping.weight = Mathf.MoveTowards(_FullBodyIK.solver.leftArmMapping.weight,
|
||||
_isLeftHandEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
_FullBodyIK.solver.rightArmMapping.weight = Mathf.MoveTowards(_FullBodyIK.solver.rightArmMapping.weight,
|
||||
_isRightHandEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
_FullBodyIK.solver.IKPositionWeight = Mathf.MoveTowards(_FullBodyIK.solver.IKPositionWeight,
|
||||
_isLeftHandEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
_ArmIK.solver.IKPositionWeight = Mathf.MoveTowards(_ArmIK.solver.IKPositionWeight,
|
||||
_isFishingLeftArmEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
_ArmIK.solver.IKRotationWeight = Mathf.MoveTowards(_ArmIK.solver.IKRotationWeight,
|
||||
_isFishingLeftArmEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing2/Unit/Unity/Mono/PlayerIK.cs.meta
Normal file
3
Assets/Scripts/Fishing2/Unit/Unity/Mono/PlayerIK.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb36ecc5b1784d948837600cf18808cd
|
||||
timeCreated: 1765121426
|
||||
12
Assets/Scripts/Fishing2/Unit/Unity/Mono/PlayerRootAsset.cs
Normal file
12
Assets/Scripts/Fishing2/Unit/Unity/Mono/PlayerRootAsset.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class PlayerRootAsset : MonoBehaviour
|
||||
{
|
||||
public Transform Root;
|
||||
public Transform Eye;
|
||||
public Transform FppLook;
|
||||
public Transform IK;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95ffc3d5f1c94a59aab905ba2d3e5de0
|
||||
timeCreated: 1765286777
|
||||
@@ -1,4 +1,6 @@
|
||||
using Fantasy.Async;
|
||||
using ECM2;
|
||||
using ECM2.Examples.FirstPerson;
|
||||
using Fantasy.Async;
|
||||
using NBC;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
@@ -13,22 +15,18 @@ namespace NBF.Fishing2
|
||||
public class UnitUnityComponent : Entity
|
||||
{
|
||||
public GameObject GameObject { get; set; }
|
||||
public GameObject ModelGameObject { get; set; }
|
||||
|
||||
public Transform Transform { get; set; }
|
||||
|
||||
public PlayerAsset Asset { get; set; }
|
||||
public PlayerModelAsset ModelAsset { get; set; }
|
||||
|
||||
public async FTask InitUnityObject()
|
||||
{
|
||||
var gameObject = PrefabsHelper.CreatePlayer(SceneSettings.Instance.Node);
|
||||
GameObject = gameObject;
|
||||
Transform = gameObject.transform;
|
||||
Transform.localPosition = new Vector3(484, 1, 422);
|
||||
Asset = gameObject.GetComponent<PlayerAsset>();
|
||||
Parent.GetOrAddComponent<FlashlightComponent>();
|
||||
Parent.GetOrAddComponent<CharacterControllerComponent>();
|
||||
}
|
||||
public CharacterMovement Character { get; set; }
|
||||
public FirstPersonCharacter FirstPerson { get; set; }
|
||||
|
||||
public PlayerRootAsset RootAsset { get; set; }
|
||||
|
||||
#region System
|
||||
|
||||
public class UnitUnityComponentDestroySystem : DestroySystem<UnitUnityComponent>
|
||||
{
|
||||
@@ -39,10 +37,38 @@ namespace NBF.Fishing2
|
||||
Object.Destroy(self.GameObject);
|
||||
}
|
||||
|
||||
self.Asset = null;
|
||||
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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,360 +2,104 @@
|
||||
|
||||
public class FloatBobberController : MonoBehaviour
|
||||
{
|
||||
[Header("水属性")]
|
||||
public float waterLevel = 0f;
|
||||
|
||||
[Header("浮漂属性")]
|
||||
public float bobberVolume = 30f; // 浮漂最大排水体积 (cm³)
|
||||
public float bobberMass = 1f; // 浮漂自重 (g)
|
||||
public float bobberHeight = 0.25f; // 浮漂总高度
|
||||
[Range(0, 1)] public float bobberFloatPartRatio = 0.7f; // 浮漂浮体部分占总高度的比例
|
||||
|
||||
[Header("配件重量")]
|
||||
public float sinkerWeight = 2f;
|
||||
[SerializeField] private Rigidbody _rigidbody;
|
||||
[Header("水属性")] public float waterLevel = 0f;
|
||||
|
||||
[Header("浮漂最大浮力")] public float bobberVolume = 30f; // 浮漂最大浮力 (cm³)
|
||||
|
||||
public float bobberHeight = 0.25f; // 浮漂长度,用来决定躺漂角度
|
||||
|
||||
[Header("配件重量")] public float sinkerWeight = 2f;
|
||||
public float baitWeight = 0.5f;
|
||||
public float hookWeight = 0.2f;
|
||||
|
||||
[Header("行为参数")]
|
||||
public float fallSpeed = 8f;
|
||||
[Header("Behaviour")] public float fallSpeed = 8f;
|
||||
public float riseSpeed = 3f;
|
||||
public float smoothDamping = 8f;
|
||||
|
||||
// 私有变量
|
||||
private float totalDownwardWeight;
|
||||
private float maxBuoyancyForce;
|
||||
private float currentSubmergedLength; // 当前浸没长度
|
||||
private float bobberFloatPartHeight; // 浮体部分高度
|
||||
|
||||
// 浮漂状态
|
||||
private float currentBuoyancy; // 当前实际浮力
|
||||
private Vector3 targetPosition;
|
||||
|
||||
// 冲击力相关
|
||||
private float impulseForce = 0f;
|
||||
private float impulseDecay = 4f;
|
||||
// public float smoothDamping = 8f; // 插值平滑
|
||||
|
||||
void Start()
|
||||
{
|
||||
InitializeBobber();
|
||||
}
|
||||
[Header("Noise")] public float noiseAmp = 0.015f;
|
||||
public float noiseFreq = 1.5f;
|
||||
|
||||
void InitializeBobber()
|
||||
{
|
||||
// 计算浮体部分高度(能够产生浮力的部分)
|
||||
bobberFloatPartHeight = bobberHeight * bobberFloatPartRatio;
|
||||
|
||||
// 最大浮力 = 浮体部分完全浸没时的排水量
|
||||
maxBuoyancyForce = bobberFloatPartHeight * 100f; // 简化计算,可根据需要调整系数
|
||||
|
||||
// 初始位置调整:让浮漂底部刚好在水面
|
||||
Vector3 pos = transform.position;
|
||||
pos.y = waterLevel - (bobberHeight * 0.5f); // 假设原点在中心,调整到浮漂底部在水面
|
||||
transform.position = pos;
|
||||
|
||||
RecalculateWeights();
|
||||
}
|
||||
float impulseForce = 0f;
|
||||
float impulseDecay = 4f;
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
SimulateBobber();
|
||||
}
|
||||
|
||||
void RecalculateWeights()
|
||||
{
|
||||
totalDownwardWeight = bobberMass + sinkerWeight + baitWeight + hookWeight;
|
||||
}
|
||||
|
||||
void SimulateBobber()
|
||||
{
|
||||
RecalculateWeights();
|
||||
|
||||
if (!_rigidbody.isKinematic) return;
|
||||
float totalDownwardWeight = sinkerWeight + baitWeight + hookWeight;
|
||||
|
||||
float maxBuoyancy = bobberVolume; // 最大浮力 = 体积
|
||||
float netBuoyancy = maxBuoyancy - totalDownwardWeight;
|
||||
|
||||
float targetY;
|
||||
|
||||
// -------------------------
|
||||
// 1. 计算当前浸没长度和浮力
|
||||
// 1. 判断浮漂应该沉多少(吃水深度)
|
||||
// -------------------------
|
||||
// 浮漂的基准位置(底部位置)
|
||||
float bobberBottomY = transform.position.y;
|
||||
float bobberTopY = bobberBottomY + bobberHeight;
|
||||
|
||||
// 计算浸没长度:浮漂底部到水面的距离,限制在0到浮体高度之间
|
||||
float submergedLength = Mathf.Clamp(waterLevel - bobberBottomY, 0f, bobberFloatPartHeight);
|
||||
currentSubmergedLength = submergedLength;
|
||||
|
||||
// 当前浮力 = (浸没长度 / 浮体高度) * 最大浮力
|
||||
float submergedRatio = submergedLength / bobberFloatPartHeight;
|
||||
currentBuoyancy = submergedRatio * maxBuoyancyForce;
|
||||
|
||||
// -------------------------
|
||||
// 2. 计算净力并决定运动
|
||||
// -------------------------
|
||||
float netForce = currentBuoyancy - totalDownwardWeight;
|
||||
|
||||
// 目标Y位置基于净力计算
|
||||
float targetY = transform.position.y;
|
||||
|
||||
if (Mathf.Abs(netForce) < 0.01f) // 基本平衡
|
||||
if (netBuoyancy > 0)
|
||||
{
|
||||
// 保持当前位置,微小波动可以在这里添加
|
||||
targetY = transform.position.y;
|
||||
float buoyPercent = Mathf.Clamp01(netBuoyancy / maxBuoyancy);
|
||||
float rise = buoyPercent * 0.1f; // 浮漂露出水面的高度
|
||||
|
||||
targetY = waterLevel + rise;
|
||||
}
|
||||
else if (netForce > 0) // 浮力大于重力,上浮
|
||||
else
|
||||
{
|
||||
float riseAmount = netForce * 0.001f * riseSpeed;
|
||||
targetY += riseAmount * Time.deltaTime;
|
||||
|
||||
// 限制不能浮出太多(露出部分不能超过非浮体部分)
|
||||
float maxBobberTopY = waterLevel + (bobberHeight - bobberFloatPartHeight);
|
||||
if (bobberTopY + riseAmount > maxBobberTopY)
|
||||
{
|
||||
targetY = maxBobberTopY - bobberHeight;
|
||||
}
|
||||
// 净浮力为负 → 说明浮漂整体被拉下,沉入水中
|
||||
float sinkDistance = Mathf.Abs(netBuoyancy) * 0.03f;
|
||||
targetY = waterLevel - sinkDistance;
|
||||
}
|
||||
else // 重力大于浮力,下沉
|
||||
{
|
||||
float sinkAmount = Mathf.Abs(netForce) * 0.001f * fallSpeed;
|
||||
targetY -= sinkAmount * Time.deltaTime;
|
||||
|
||||
// 限制不能沉没太多(浮体部分完全浸没后浮力达到最大)
|
||||
float minBobberBottomY = waterLevel - bobberFloatPartHeight;
|
||||
if (bobberBottomY - sinkAmount < minBobberBottomY)
|
||||
{
|
||||
targetY = minBobberBottomY;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// 3. 应用冲击力
|
||||
// -------------------------
|
||||
if (Mathf.Abs(impulseForce) > 0.01f)
|
||||
|
||||
targetY += Mathf.Sin(Time.time * noiseFreq) * noiseAmp; // 微扰模拟波浪
|
||||
|
||||
// 顿口/顶漂力
|
||||
if (impulseForce != 0f)
|
||||
{
|
||||
targetY += impulseForce * Time.deltaTime;
|
||||
impulseForce = Mathf.Lerp(impulseForce, 0, Time.deltaTime * impulseDecay);
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// 4. 平滑移动
|
||||
// -------------------------
|
||||
targetPosition = new Vector3(transform.position.x, targetY, transform.position.z);
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * smoothDamping);
|
||||
|
||||
// 调试信息
|
||||
DebugDisplay();
|
||||
}
|
||||
|
||||
void DebugDisplay()
|
||||
{
|
||||
Debug.Log($"浸没比例: {(currentSubmergedLength / bobberFloatPartHeight):P1} " +
|
||||
$"当前浮力: {currentBuoyancy:F2} " +
|
||||
$"总重力: {totalDownwardWeight:F2} " +
|
||||
$"净力: {currentBuoyancy - totalDownwardWeight:F2}");
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
// 公共方法 - 用于调漂和鱼咬钩
|
||||
// ----------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// 调整配重(用于调漂)
|
||||
/// </summary>
|
||||
public void AdjustSinkerWeight(float newWeight)
|
||||
{
|
||||
sinkerWeight = newWeight;
|
||||
RecalculateWeights();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前调目(浮漂露出水面的格数)
|
||||
/// </summary>
|
||||
public float GetCurrentVisibleMarks()
|
||||
{
|
||||
float bobberBottomY = transform.position.y;
|
||||
float visibleHeight = (bobberBottomY + bobberHeight) - waterLevel;
|
||||
float markHeight = bobberHeight / 10f; // 假设浮漂有10格
|
||||
return Mathf.Max(0, visibleHeight / markHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置目标调目(自动计算需要的配重)
|
||||
/// </summary>
|
||||
public void SetTargetMarks(float targetMarks)
|
||||
{
|
||||
float markHeight = bobberHeight / 10f;
|
||||
float targetVisibleHeight = targetMarks * markHeight;
|
||||
float targetSubmergedLength = bobberFloatPartHeight - targetVisibleHeight;
|
||||
|
||||
// 需要的浮力 = (浸没长度 / 浮体高度) * 最大浮力
|
||||
float requiredBuoyancy = (targetSubmergedLength / bobberFloatPartHeight) * maxBuoyancyForce;
|
||||
|
||||
// 配重 = 浮漂自重 + 钩饵重 - 需要的浮力
|
||||
float requiredSinkerWeight = bobberMass + hookWeight + baitWeight - requiredBuoyancy;
|
||||
|
||||
sinkerWeight = Mathf.Max(0, requiredSinkerWeight);
|
||||
RecalculateWeights();
|
||||
|
||||
// -----------------------------
|
||||
// ③ 上浮 / 下沉差速
|
||||
// -----------------------------
|
||||
float y = transform.position.y;
|
||||
float diff = targetY - y;
|
||||
|
||||
if (diff > 0) // 上浮
|
||||
y += diff * Time.deltaTime * riseSpeed;
|
||||
else
|
||||
y += diff * Time.deltaTime * fallSpeed;
|
||||
|
||||
transform.position = new Vector3(transform.position.x, y, transform.position.z);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------
|
||||
// 鱼咬钩相关方法
|
||||
// 外部控制接口
|
||||
// ----------------------------------------
|
||||
|
||||
public void TriggerDownPulse(float strength = 0.8f)
|
||||
|
||||
public void TriggerDownPulse(float s = 0.8f)
|
||||
{
|
||||
impulseForce -= Mathf.Abs(strength);
|
||||
impulseForce -= Mathf.Abs(s);
|
||||
}
|
||||
|
||||
public void TriggerUpPulse(float strength = 0.8f)
|
||||
public void TriggerUpPulse(float s = 0.8f)
|
||||
{
|
||||
impulseForce += Mathf.Abs(strength);
|
||||
impulseForce += Mathf.Abs(s);
|
||||
}
|
||||
|
||||
public void AddFishPull(float pullForce)
|
||||
public void AddFishPull(float v)
|
||||
{
|
||||
// 鱼的拉力相当于增加向下的力
|
||||
sinkerWeight += pullForce;
|
||||
sinkerWeight += v;
|
||||
}
|
||||
|
||||
public void ReleaseFishPull(float pullForce)
|
||||
public void ReleaseFishPull(float v)
|
||||
{
|
||||
sinkerWeight -= pullForce;
|
||||
sinkerWeight -= v;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
// 可视化调试
|
||||
// ----------------------------------------
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
// 绘制水面
|
||||
Gizmos.color = Color.blue;
|
||||
Gizmos.DrawLine(new Vector3(-1, waterLevel, 0), new Vector3(1, waterLevel, 0));
|
||||
|
||||
// 绘制浮漂
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
// 浸没部分用蓝色
|
||||
Gizmos.color = Color.cyan;
|
||||
float submergedBottom = transform.position.y;
|
||||
float submergedTop = submergedBottom + currentSubmergedLength;
|
||||
Gizmos.DrawWireCube(
|
||||
new Vector3(transform.position.x, (submergedBottom + submergedTop) * 0.5f, transform.position.z),
|
||||
new Vector3(0.1f, currentSubmergedLength, 0.1f)
|
||||
);
|
||||
|
||||
// 露出部分用红色
|
||||
Gizmos.color = Color.red;
|
||||
float visibleBottom = submergedTop;
|
||||
float visibleTop = transform.position.y + bobberHeight;
|
||||
float visibleHeight = visibleTop - visibleBottom;
|
||||
if (visibleHeight > 0)
|
||||
{
|
||||
Gizmos.DrawWireCube(
|
||||
new Vector3(transform.position.x, (visibleBottom + visibleTop) * 0.5f, transform.position.z),
|
||||
new Vector3(0.1f, visibleHeight, 0.1f)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// using UnityEngine;
|
||||
//
|
||||
// public class FloatBobberController : MonoBehaviour
|
||||
// {
|
||||
// [Header("水属性")] public float waterLevel = 0f;
|
||||
// [Header("浮漂最大浮力")] public float bobberVolume = 30f; // 浮漂最大浮力 (cm³)
|
||||
// [Header("浮漂自重")] public float bobberMass = 1f; // 浮漂自重 (g)
|
||||
// public float bobberHeight = 0.25f; // 浮漂长度,用来决定躺漂角度
|
||||
//
|
||||
// [Header("配件重量")] public float sinkerWeight = 2f;
|
||||
// public float baitWeight = 0.5f;
|
||||
// public float hookWeight = 0.2f;
|
||||
//
|
||||
// [Header("Behaviour")] public float fallSpeed = 8f;
|
||||
// public float riseSpeed = 3f;
|
||||
// public float smoothDamping = 8f; // 插值平滑
|
||||
//
|
||||
// // [Header("Noise")] public float noiseAmp = 0.015f;
|
||||
// // public float noiseFreq = 1.5f;
|
||||
//
|
||||
// float impulseForce = 0f;
|
||||
// float impulseDecay = 4f;
|
||||
//
|
||||
// void FixedUpdate()
|
||||
// {
|
||||
// SimulateBobber();
|
||||
// }
|
||||
//
|
||||
// void SimulateBobber()
|
||||
// {
|
||||
// float totalDownwardWeight = bobberMass + sinkerWeight + baitWeight + hookWeight;
|
||||
//
|
||||
// float maxBuoyancy = bobberVolume; // 最大浮力 = 体积
|
||||
// float netBuoyancy = maxBuoyancy - totalDownwardWeight;
|
||||
//
|
||||
// float targetY;
|
||||
//
|
||||
// // -------------------------
|
||||
// // 1. 判断浮漂应该沉多少(吃水深度)
|
||||
// // -------------------------
|
||||
// if (netBuoyancy > 0)
|
||||
// {
|
||||
// float buoyPercent = Mathf.Clamp01(netBuoyancy / maxBuoyancy);
|
||||
// float rise = buoyPercent * 0.1f; // 浮漂露出水面的高度
|
||||
//
|
||||
// targetY = waterLevel + rise;
|
||||
//
|
||||
// // targetY += Mathf.Sin(Time.time * noiseFreq) * noiseAmp; // 微扰模拟波浪
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 净浮力为负 → 说明浮漂整体被拉下,沉入水中
|
||||
// float sinkDistance = Mathf.Abs(netBuoyancy) * 0.03f;
|
||||
// targetY = waterLevel - sinkDistance;
|
||||
// }
|
||||
//
|
||||
// // 顿口/顶漂力
|
||||
// if (impulseForce != 0f)
|
||||
// {
|
||||
// targetY += impulseForce * Time.deltaTime;
|
||||
// impulseForce = Mathf.Lerp(impulseForce, 0, Time.deltaTime * impulseDecay);
|
||||
// }
|
||||
//
|
||||
// // -----------------------------
|
||||
// // ③ 上浮 / 下沉差速
|
||||
// // -----------------------------
|
||||
// float y = transform.position.y;
|
||||
// float diff = targetY - y;
|
||||
//
|
||||
// if (diff > 0) // 上浮
|
||||
// y += diff * Time.deltaTime * riseSpeed;
|
||||
// else
|
||||
// y += diff * Time.deltaTime * fallSpeed;
|
||||
//
|
||||
// transform.position = new Vector3(transform.position.x, y, transform.position.z);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // ----------------------------------------
|
||||
// // 外部控制接口
|
||||
// // ----------------------------------------
|
||||
//
|
||||
// public void TriggerDownPulse(float s = 0.8f)
|
||||
// {
|
||||
// impulseForce -= Mathf.Abs(s);
|
||||
// }
|
||||
//
|
||||
// public void TriggerUpPulse(float s = 0.8f)
|
||||
// {
|
||||
// impulseForce += Mathf.Abs(s);
|
||||
// }
|
||||
//
|
||||
// public void AddFishPull(float v)
|
||||
// {
|
||||
// sinkerWeight += v;
|
||||
// }
|
||||
//
|
||||
// public void ReleaseFishPull(float v)
|
||||
// {
|
||||
// sinkerWeight -= v;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -7,26 +7,28 @@ namespace NBF
|
||||
public class Game : MonoBehaviour
|
||||
{
|
||||
public static Game Instance { get; private set; }
|
||||
|
||||
|
||||
public static InputComponent Input;
|
||||
|
||||
/// <summary>
|
||||
/// 主摄像机
|
||||
/// </summary>
|
||||
public static Camera MainCamera { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 摄像机配置
|
||||
/// </summary>
|
||||
// public static CameraScriptObject CameraConfig { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 自身的unit id
|
||||
/// </summary>
|
||||
public static long SelfId;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
// CameraConfig = Resources.Load<CameraScriptObject>(nameof(CameraConfig));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
using System;
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public enum PlayerState
|
||||
{
|
||||
idle = 0,
|
||||
move = 1,
|
||||
prepare = 2,
|
||||
casting = 3,
|
||||
fishing = 4,
|
||||
baitFlies = 5,
|
||||
fight = 6,
|
||||
fishView = 7,
|
||||
collectFish = 8,
|
||||
throwFish = 9,
|
||||
vehicle = 10,
|
||||
swiming = 11,
|
||||
flyModeDebug = 12,
|
||||
vehicleFishing = 13,
|
||||
preciseCastIdle = 14,
|
||||
preciseCastThrow = 15
|
||||
}
|
||||
|
||||
public class PlayerAsset : MonoBehaviour
|
||||
{
|
||||
public Transform FPSCamera;
|
||||
public GameObject FishingLight;
|
||||
public Animator Animator { get; private set; }
|
||||
public LookAtIK LookAtIK { get; private set; }
|
||||
public CharacterController CharacterController { get; private set; }
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
#region 动画
|
||||
|
||||
#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");
|
||||
|
||||
#endregion
|
||||
|
||||
#region 动画事件回调
|
||||
|
||||
/// <summary>
|
||||
/// 抛竿开始
|
||||
/// </summary>
|
||||
public void RodForceThrowStart()
|
||||
{
|
||||
// if (Player.Fsm.CurrentState is PlayerThrow playerThrow)
|
||||
// {
|
||||
// playerThrow.RodForceThrowStart();
|
||||
// }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Animator = GetComponent<Animator>();
|
||||
LookAtIK = GetComponent<LookAtIK>();
|
||||
CharacterController = GetComponent<CharacterController>();
|
||||
Rigidbody = GetComponent<Rigidbody>();
|
||||
LookAtIK.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
Assets/Scripts/Model/Assets/PlayerModelAsset.cs
Normal file
47
Assets/Scripts/Model/Assets/PlayerModelAsset.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using KINEMATION.MagicBlend.Runtime;
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public enum PlayerState
|
||||
{
|
||||
idle = 0,
|
||||
move = 1,
|
||||
prepare = 2,
|
||||
casting = 3,
|
||||
fishing = 4,
|
||||
baitFlies = 5,
|
||||
fight = 6,
|
||||
fishView = 7,
|
||||
collectFish = 8,
|
||||
throwFish = 9,
|
||||
vehicle = 10,
|
||||
swiming = 11,
|
||||
flyModeDebug = 12,
|
||||
vehicleFishing = 13,
|
||||
preciseCastIdle = 14,
|
||||
preciseCastThrow = 15
|
||||
}
|
||||
|
||||
public class PlayerModelAsset : MonoBehaviour
|
||||
{
|
||||
public Animator Animator { get; private set; }
|
||||
public PlayerIK IK { get; private set; }
|
||||
public MagicBlending MagicBlending { get; private set; }
|
||||
|
||||
public Transform NeckTransform;
|
||||
public LookAtIK LookIk;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
LookIk = GetComponent<LookAtIK>();
|
||||
Animator = GetComponent<Animator>();
|
||||
Animator.keepAnimatorStateOnDisable = true;
|
||||
MagicBlending = GetComponent<MagicBlending>();
|
||||
IK = GetComponent<PlayerIK>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,14 @@ namespace NBF
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
#if CINEMACHINE_URP
|
||||
int i = 0;
|
||||
#endif
|
||||
Init();
|
||||
DontDestroyOnLoad(gameObject);
|
||||
DepthOfField dof = ScriptableObject.CreateInstance<DepthOfField>();
|
||||
dof.aperture.value = 0;
|
||||
dof.focalLength.value = 0;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
|
||||
22
Assets/Scripts/Model/Common/Enum/MapUnitState.cs
Normal file
22
Assets/Scripts/Model/Common/Enum/MapUnitState.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace NBF
|
||||
{
|
||||
public enum MapUnitState
|
||||
{
|
||||
idle = 0,
|
||||
move = 1,
|
||||
prepare = 2,
|
||||
casting = 3,
|
||||
fishing = 4,
|
||||
baitFlies = 5,
|
||||
fight = 6,
|
||||
fishView = 7,
|
||||
collectFish = 8,
|
||||
throwFish = 9,
|
||||
vehicle = 10,
|
||||
swiming = 11,
|
||||
flyModeDebug = 12,
|
||||
vehicleFishing = 13,
|
||||
preciseCastIdle = 14,
|
||||
preciseCastThrow = 15
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Model/Common/Enum/MapUnitState.cs.meta
Normal file
3
Assets/Scripts/Model/Common/Enum/MapUnitState.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a25ab9f9b4140c7bd3e463da484301e
|
||||
timeCreated: 1765284104
|
||||
@@ -80,7 +80,7 @@ namespace NBF
|
||||
Log.Warning("账号没有进入过地图,进入新手引导地图");
|
||||
mapId = 99;
|
||||
}
|
||||
// await MapHelper.EnterMap(mapId, role.RoomCode);
|
||||
await MapHelper.EnterMap(mapId, role.RoomCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,10 @@ namespace NBC
|
||||
|
||||
public string Get(string key)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
if (_currentLanguageDictionary != null && _currentLanguageDictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
return value;
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace NBF.Fishing2
|
||||
scene.AddComponent<ObjectWait>();
|
||||
scene.AddComponent<MapManageComponent>();
|
||||
scene.AddComponent<CameraComponent>();
|
||||
scene.AddComponent<CursorComponent>();
|
||||
var input = scene.AddComponent<InputComponent>();
|
||||
scene.AddComponent<SettingComponent>();
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace NBF
|
||||
if (action == InputDef.UI.Back)
|
||||
{
|
||||
if (!IsTop) return;
|
||||
HomePanel.Show();
|
||||
// HomePanel.Show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace NBF
|
||||
|
||||
// BagPanel.Show();
|
||||
// BagSlotPanel.Show();
|
||||
FishingShopPanel.Show();
|
||||
// FishingShopPanel.Show();
|
||||
|
||||
Del();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user