注释脚本
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcae353a013f4bd8bd4818abbcbe6959
|
||||
timeCreated: 1766743259
|
||||
@@ -1,55 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class ReelAnimator : MonoBehaviour
|
||||
{
|
||||
public FReel Reel;
|
||||
|
||||
private Animator _animator;
|
||||
|
||||
#region 参数定义
|
||||
|
||||
private static readonly int ReelingHash = Animator.StringToHash("Reeling");
|
||||
private static readonly int LineOutHash = Animator.StringToHash("LineOut");
|
||||
private static readonly int UnlockHash = Animator.StringToHash("Unlock");
|
||||
private static readonly int LineOutUnlockHash = Animator.StringToHash("LineOutUnlock");
|
||||
|
||||
public float Reeling
|
||||
{
|
||||
get => _animator.GetFloat(ReelingHash);
|
||||
set => _animator.SetFloat(ReelingHash, value);
|
||||
}
|
||||
|
||||
public float Reeling2
|
||||
{
|
||||
get => _animator.GetFloat(ReelingHash);
|
||||
set => _animator.SetFloat(ReelingHash, value);
|
||||
}
|
||||
|
||||
public float LineOut
|
||||
{
|
||||
get => _animator.GetFloat(LineOutHash);
|
||||
set => _animator.SetFloat(LineOutHash, value);
|
||||
}
|
||||
|
||||
public bool Unlock
|
||||
{
|
||||
get => _animator.GetBool(UnlockHash);
|
||||
set => _animator.SetBool(UnlockHash, value);
|
||||
}
|
||||
|
||||
public bool LineOutUnlock
|
||||
{
|
||||
get => _animator.GetBool(LineOutUnlockHash);
|
||||
set => _animator.SetBool(LineOutUnlockHash, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dad5b24d68464595b58a0d8fea28a10b
|
||||
timeCreated: 1766743262
|
||||
@@ -1,40 +0,0 @@
|
||||
// using UnityEngine;
|
||||
//
|
||||
// namespace NBF
|
||||
// {
|
||||
// public class BobberController : MonoBehaviour
|
||||
// {
|
||||
// [SerializeField] private Rigidbody _rbody;
|
||||
//
|
||||
// [SerializeField] private ConfigurableJoint joint;
|
||||
// // [SerializeField] private Buoyancy _buoyancy;
|
||||
// public Rigidbody rbody => _rbody;
|
||||
//
|
||||
// public Rigidbody JointRb => joint.connectedBody;
|
||||
//
|
||||
// public void SetJoint(Rigidbody rb)
|
||||
// {
|
||||
// joint = joint == null ? GetComponent<ConfigurableJoint>() : joint;
|
||||
// joint.connectedBody = rb;
|
||||
// }
|
||||
//
|
||||
// public void SetJointDistance(float limit)
|
||||
// {
|
||||
// joint.linearLimit = new SoftJointLimit
|
||||
// {
|
||||
// limit = limit
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// public void SetDetectCollisionEnabled(bool en)
|
||||
// {
|
||||
// _rbody.detectCollisions = en;
|
||||
// // _buoyancy.EnablePhysics(en);
|
||||
// }
|
||||
//
|
||||
// public void SetVelocity(Vector3 velocity)
|
||||
// {
|
||||
// _rbody.linearVelocity = velocity;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e9411b5edc6466a8014c59e3821bbaa
|
||||
timeCreated: 1768918059
|
||||
@@ -1,71 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Entitas;
|
||||
using NBF.Fishing2;
|
||||
using RootMotion.FinalIK;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class Fishing
|
||||
{
|
||||
private static Fishing _instance;
|
||||
|
||||
public static Fishing Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
_instance ??= new Fishing();
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public MapRoom OldMap { get; private set; }
|
||||
|
||||
public MapRoom Map { get; private set; }
|
||||
|
||||
|
||||
public async FTask<bool> Go(int mapId, string roomCode = "")
|
||||
{
|
||||
if (mapId == 0)
|
||||
{
|
||||
Log.Warning("账号没有进入过地图,进入新手引导地图");
|
||||
mapId = 99;
|
||||
}
|
||||
|
||||
var response = (G2C_EnterMapResponse)await Net.Call(new C2G_EnterMapRequest()
|
||||
{
|
||||
MapId = mapId,
|
||||
RoomCode = roomCode
|
||||
});
|
||||
Log.Info($"进入地图请求返回={response.ErrorCode}");
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
Notices.Error("enter room error");
|
||||
return false;
|
||||
}
|
||||
LoadingPanel.Show();
|
||||
await ChangeMap(response.MapId, response.RoomCode, response.Units);
|
||||
LoadingPanel.Hide();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public async FTask ChangeMap(int mapId, string roomCode, List<MapUnitInfo> units)
|
||||
{
|
||||
OldMap = Map;
|
||||
Map = Entity.Create<MapRoom>(Game.Main,true, true);
|
||||
Map.Code = roomCode;
|
||||
Map.Map = mapId;
|
||||
var sceneName = "Map1";
|
||||
//加载场景==
|
||||
await SceneHelper.LoadScene(sceneName);
|
||||
foreach (var mapUnitInfo in units)
|
||||
{
|
||||
Map.AddUnit(mapUnitInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0afcee9eb5f848e08b2fae2cc673b6d8
|
||||
timeCreated: 1766414593
|
||||
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FixedLine : MonoBehaviour
|
||||
{
|
||||
public Transform target;
|
||||
private Rigidbody _rigidbody;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rigidbody = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
FixLine();
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
FixLine();
|
||||
}
|
||||
|
||||
|
||||
private void FixLine()
|
||||
{
|
||||
if (!target) return;
|
||||
_rigidbody.MovePosition(target.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec22ad0246c24123a6511e60e753ee38
|
||||
timeCreated: 1766586205
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4177c0c4cf94787b06ec92973ba4722
|
||||
timeCreated: 1766412118
|
||||
@@ -1,67 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network;
|
||||
using NBC;
|
||||
using NBF.Fishing2;
|
||||
using Newtonsoft.Json;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public static class LoginHelper
|
||||
{
|
||||
private static Session _session;
|
||||
|
||||
public static async FTask Login(string account)
|
||||
{
|
||||
_session = Net.CreateSession("127.0.0.1:20001");
|
||||
|
||||
// _session.Scene.AddComponent<UnitUnityComponent>();
|
||||
|
||||
var acc = account;
|
||||
|
||||
// 发送登录的请求给服务器
|
||||
var response = (A2C_LoginResponse)await Net.Call(new C2A_LoginRequest()
|
||||
{
|
||||
Username = acc,
|
||||
Password = acc,
|
||||
LoginType = 1
|
||||
});
|
||||
|
||||
if (response.ErrorCode != 0)
|
||||
{
|
||||
Log.Error($"登录发生错误{response.ErrorCode}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Game.Main.GetComponent<JWTParseComponent>().Parse(response.ToKen, out var payload))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据ToKen返回的Address登录到Gate服务器
|
||||
_session = Net.CreateSession(payload.Address);
|
||||
|
||||
// 发送登录请求到Gate服务器
|
||||
var loginResponse = (G2C_LoginResponse)await Net.Call(new C2G_LoginRequest()
|
||||
{
|
||||
ToKen = response.ToKen
|
||||
});
|
||||
if (loginResponse.ErrorCode != 0)
|
||||
{
|
||||
Log.Error($"登录发生错误{loginResponse.ErrorCode}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// var role = Game.Main.AddComponent<Role>(loginResponse.RoleId);
|
||||
RoleModel.Instance.Id = loginResponse.RoleId;
|
||||
Log.Info($"登录到Gate服务器成功!ErrorCode:{loginResponse.ErrorCode}");
|
||||
await RoleModel.Instance.GetRoleInfo();
|
||||
Log.Info(
|
||||
$"获取角色信息成功!roleId={RoleModel.Instance.Id} Room={RoleModel.Instance.RoomCode} RoleInfo={JsonConvert.SerializeObject(RoleModel.Instance.Info)}");
|
||||
//获取背包数据
|
||||
await RoleModel.Instance.GetBagInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 031ed023449844cdb9d6c4eb5d7fee90
|
||||
timeCreated: 1755698636
|
||||
@@ -1,115 +0,0 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using Fantasy;
|
||||
// using Fantasy.Async;
|
||||
// using NBC;
|
||||
// using Fantasy.Entitas;
|
||||
// using UnityEngine;
|
||||
// using Log = NBC.Log;
|
||||
// using Object = System.Object;
|
||||
//
|
||||
// namespace NBF.Fishing2
|
||||
// {
|
||||
// public static class MapHelper
|
||||
// {
|
||||
// #region Map
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 开始进入地图
|
||||
// /// </summary>
|
||||
// public static async FTask<int> EnterMap(int mapId, string roomCode = "")
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var root = Game.Main;
|
||||
//
|
||||
// var response = (G2C_EnterMapResponse)await Net.Call(new C2G_EnterMapRequest()
|
||||
// {
|
||||
// MapId = mapId,
|
||||
// RoomCode = roomCode
|
||||
// });
|
||||
// Log.Info($"进入地图请求返回={response.ErrorCode}");
|
||||
//
|
||||
// await ChangeMap(response.MapId, response.RoomCode, response.Units);
|
||||
// // 等待场景切换完成
|
||||
// // await root.GetComponent<ObjectWait>().Wait<Wait_SceneChangeFinish>();
|
||||
// Log.Info($"等待场景切换结束");
|
||||
// await root.EventComponent.PublishAsync(new EnterMapFinish());
|
||||
// LoadingPanel.Hide();
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Log.Error(e);
|
||||
// return ErrorCode.Error;
|
||||
// }
|
||||
//
|
||||
// return ErrorCode.Success;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public static async FTask ChangeMap(int mapId, string roomCode, List<MapUnitInfo> units)
|
||||
// {
|
||||
// LoadingPanel.Show();
|
||||
//
|
||||
// var oldMap = App.Main.GetComponent<Map>();
|
||||
// await oldMap.UnLoadMap();
|
||||
//
|
||||
// var map = App.Main.AddComponent<Map>();
|
||||
// map.MapId = mapId;
|
||||
// map.RoomCode = roomCode;
|
||||
// map.SelfId = Game.SelfId;
|
||||
// foreach (var mapUnitInfo in units)
|
||||
// {
|
||||
// map.CreateMapUnit(mapUnitInfo);
|
||||
// }
|
||||
//
|
||||
// await map.LoadMap();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 卸载旧场景
|
||||
// /// </summary>
|
||||
// /// <param name="self"></param>
|
||||
// public static async FTask UnLoadMap(this Map self)
|
||||
// {
|
||||
// await FTask.CompletedTask;
|
||||
// }
|
||||
//
|
||||
// public static async FTask LoadMap(this Map self)
|
||||
// {
|
||||
// var sceneName = "Map1";
|
||||
// //加载场景==
|
||||
// await SceneHelper.LoadScene(sceneName);
|
||||
// await self.LoadAllUnit();
|
||||
// FishingPanel.Show();
|
||||
//
|
||||
// // 通知等待场景切换的协程
|
||||
// App.Main.GetComponent<ObjectWait>().Notify(new Wait_SceneChangeFinish());
|
||||
// }
|
||||
//
|
||||
// #endregion
|
||||
//
|
||||
// #region Unit
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 加载所有unit单位
|
||||
// /// </summary>
|
||||
// /// <param name="self"></param>
|
||||
// public static async FTask LoadAllUnit(this Map self)
|
||||
// {
|
||||
// foreach (var (_, unit) in self.Units)
|
||||
// {
|
||||
// await unit.CreateView();
|
||||
// }
|
||||
//
|
||||
// var cameraComponent = self.Scene.GetComponent<CameraComponent>();
|
||||
// if (cameraComponent != null)
|
||||
// {
|
||||
// cameraComponent.Mode = CameraShowMode.FPP;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #endregion
|
||||
// }
|
||||
// }
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfc04c7d83084b7784cb7cf69dde1be6
|
||||
timeCreated: 1756132207
|
||||
@@ -1,48 +0,0 @@
|
||||
using Fantasy;
|
||||
using NBC;
|
||||
using NBC.Asset;
|
||||
using NBF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public static class PrefabsHelper
|
||||
{
|
||||
public static GameObject LoadPrefab(string path, Transform parent = null)
|
||||
{
|
||||
var prefab = Assets.Load<GameObject>(path);
|
||||
if (prefab == null)
|
||||
{
|
||||
|
||||
}
|
||||
return parent == null ? Object.Instantiate(prefab) : Object.Instantiate(prefab, parent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建角色预制体
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
/// <param name="modelName"></param>
|
||||
/// <returns></returns>
|
||||
public static GameObject CreatePlayer(Transform parent, string modelName = "Player")
|
||||
{
|
||||
var model = LoadPrefab($"Assets/ResRaw/Prefabs/Player/{modelName}.prefab", parent);
|
||||
return model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建物品预制体
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="isPreview">是否预览模式</param>
|
||||
/// <returns></returns>
|
||||
public static GameObject CreateItem(cfg.Item config, bool isPreview = false)
|
||||
{
|
||||
//创建主物体
|
||||
var mainObject = LoadPrefab(config.GetFullModelPath());
|
||||
//创建配件
|
||||
|
||||
return mainObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18ffcf16981040b2a88990281adcb4ac
|
||||
timeCreated: 1756451102
|
||||
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using Fantasy.Async;
|
||||
using NBC;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public static class SceneHelper
|
||||
{
|
||||
public static async FTask LoadScene(string sceneName)
|
||||
{
|
||||
try
|
||||
{
|
||||
Game.Main.EventComponent.Publish(new SceneChangeStart());
|
||||
LoadingPanel.Show();
|
||||
var asyncOperation = SceneManager.LoadSceneAsync(sceneName);
|
||||
if (asyncOperation == null) throw new Exception($"Scene not found,name={sceneName}");
|
||||
while (true)
|
||||
{
|
||||
await Game.Main.EventComponent.PublishAsync(new LoadingProgress()
|
||||
{
|
||||
Progress = asyncOperation.progress
|
||||
});
|
||||
LoadingPanel.SetProgress(asyncOperation.progress);
|
||||
// 等待0.5秒后执行下面的逻辑。
|
||||
await Game.Main.TimerComponent.Net.WaitAsync(500);
|
||||
if (asyncOperation.isDone)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4a2e9c0ac6d4faabbec4bccdb7a2917
|
||||
timeCreated: 1756367987
|
||||
@@ -1,59 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class LureController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Rigidbody rBody;
|
||||
[SerializeField] private ConfigurableJoint joint;
|
||||
public Rigidbody RBody => rBody;
|
||||
|
||||
public ConfigurableJoint Joint => joint;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
RBody.detectCollisions = true;
|
||||
RBody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
|
||||
RBody.interpolation = RigidbodyInterpolation.Interpolate;
|
||||
}
|
||||
|
||||
public void SetJoint(Rigidbody rb)
|
||||
{
|
||||
joint.connectedBody = rb;
|
||||
}
|
||||
|
||||
|
||||
public void EnableCollision(bool enable)
|
||||
{
|
||||
if (rBody == null)
|
||||
{
|
||||
rBody = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
// rBody.detectCollisions = enable;
|
||||
}
|
||||
|
||||
public void SetKinematic(bool value)
|
||||
{
|
||||
rBody.isKinematic = value;
|
||||
}
|
||||
|
||||
public void SetJointDistance(float limit)
|
||||
{
|
||||
joint.linearLimit = new SoftJointLimit
|
||||
{
|
||||
limit = limit
|
||||
};
|
||||
}
|
||||
|
||||
private void OnCollisionEnter(Collision other)
|
||||
{
|
||||
Debug.Log($"OnCollisionEnter:{other.gameObject.name}");
|
||||
}
|
||||
private void OnCollisionExit(Collision other)
|
||||
{
|
||||
Debug.Log($"OnCollisionExit:{other.gameObject.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed5bbbc032ec4ca1bb56991d9141e311
|
||||
timeCreated: 1768918224
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b727e6041c1e459aabd0d5c41752dd8e
|
||||
timeCreated: 1773036926
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b61ff9bc02946a287bd0cca1aa2b6cb
|
||||
timeCreated: 1773037834
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c67e0c4e3e30462d88970a3c0b4569e8
|
||||
timeCreated: 1773123725
|
||||
@@ -1,115 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using NBF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 玩家物品
|
||||
/// </summary>
|
||||
public class PlayerItem : Entity
|
||||
{
|
||||
public Player Owner;
|
||||
|
||||
/// <summary>
|
||||
/// 配置id
|
||||
/// </summary>
|
||||
public int ConfigID;
|
||||
|
||||
public List<int> BindItems = new List<int>();
|
||||
|
||||
#region Rod专属
|
||||
|
||||
private bool _stretchRope = true;
|
||||
|
||||
public bool StretchRope
|
||||
{
|
||||
get => _stretchRope;
|
||||
set
|
||||
{
|
||||
_stretchRope = value;
|
||||
Scene.EventComponent.Publish(new PlayerItemRodLingChangeEvent
|
||||
{
|
||||
Item = this
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private float _lineLength = 4.2f;
|
||||
|
||||
/// <summary>
|
||||
/// 线长度
|
||||
/// </summary>
|
||||
public float LineLength
|
||||
{
|
||||
get => _lineLength;
|
||||
set
|
||||
{
|
||||
_lineLength = value;
|
||||
Scene.EventComponent.Publish(new PlayerItemRodLingChangeEvent
|
||||
{
|
||||
Item = this
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private float _floatLength = 0.7f;
|
||||
|
||||
/// <summary>
|
||||
/// 浮漂线长度
|
||||
/// </summary>
|
||||
public float FloatLength
|
||||
{
|
||||
get => _floatLength;
|
||||
set
|
||||
{
|
||||
_floatLength = value;
|
||||
Scene.EventComponent.Publish(new PlayerItemRodLingChangeEvent
|
||||
{
|
||||
Item = this
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private float _tension;
|
||||
|
||||
/// <summary>
|
||||
/// 拉力
|
||||
/// </summary>
|
||||
public float Tension
|
||||
{
|
||||
get => _tension;
|
||||
set
|
||||
{
|
||||
if (!Mathf.Approximately(_tension, value))
|
||||
{
|
||||
_tension = value;
|
||||
}
|
||||
|
||||
// Scene.EventComponent.Publish(new PlayerItemRodLingChangeEvent
|
||||
// {
|
||||
// Item = this
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public void Init(Player player, int configId, List<int> bindItems)
|
||||
{
|
||||
Owner = player;
|
||||
ConfigID = configId;
|
||||
BindItems.Clear();
|
||||
BindItems.AddRange(bindItems);
|
||||
// var itemType = bindInfo.Item.GetItemType();
|
||||
// if (itemType == ItemType.Rod)
|
||||
// {
|
||||
// var rod = AddComponent<PlayerItemRod>();
|
||||
// rod.Init(bindInfo);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6649b122db2f46aea8147228c674a38c
|
||||
timeCreated: 1773037313
|
||||
@@ -1,63 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 地图房间
|
||||
/// </summary>
|
||||
public class MapRoom : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否本地房间
|
||||
/// </summary>
|
||||
public bool IsLocalRoom;
|
||||
|
||||
/// <summary>
|
||||
/// 房间序号id
|
||||
/// </summary>
|
||||
public int RoomId;
|
||||
|
||||
/// <summary>
|
||||
/// 房间代码
|
||||
/// </summary>
|
||||
public string Code = string.Empty;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 房间玩家
|
||||
/// </summary>
|
||||
public Dictionary<long, Player> Units = new Dictionary<long, Player>();
|
||||
|
||||
/// <summary>
|
||||
/// 房主
|
||||
/// </summary>
|
||||
public long Owner;
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public long CreateTime;
|
||||
|
||||
/// <summary>
|
||||
/// 房间地图
|
||||
/// </summary>
|
||||
public int Map;
|
||||
|
||||
public void AddUnit(MapUnitInfo unit)
|
||||
{
|
||||
var player = Create<Player>(Game.Main, unit.Id, true, true);
|
||||
Units[unit.Id] = player;
|
||||
player.InitPlayer(unit);
|
||||
}
|
||||
|
||||
public void RemoveUnit(long id)
|
||||
{
|
||||
if (Units.Remove(id, out var player))
|
||||
{
|
||||
player.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41009853ac444d87809e98fae2d1c597
|
||||
timeCreated: 1773036879
|
||||
@@ -1,157 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using NBF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class Player : Entity
|
||||
{
|
||||
// ========== 本地状态 ==========
|
||||
/// <summary>
|
||||
/// 是否本地玩家
|
||||
/// </summary>
|
||||
public bool IsLocalPlayer;
|
||||
|
||||
/// <summary>
|
||||
/// 是否切换物品中
|
||||
/// </summary>
|
||||
public bool IsChangeItemIng;
|
||||
|
||||
public bool IsLureRod => false;
|
||||
|
||||
public bool IsSelf => RoleModel.Instance.Id == Id;
|
||||
|
||||
// ========== 物理状态(高频同步) ==========
|
||||
public Vector3 Position;
|
||||
public Quaternion Rotation;
|
||||
public Vector2 MoveInput;
|
||||
public float Speed;
|
||||
public float RotationSpeed;
|
||||
public bool IsGrounded;
|
||||
public bool Run;
|
||||
public float EyeAngle;
|
||||
|
||||
/// <summary>
|
||||
/// 标志量
|
||||
/// </summary>
|
||||
public long TagValue;
|
||||
|
||||
/// <summary>
|
||||
/// 上一个状态
|
||||
/// </summary>
|
||||
public PlayerState PreviousState;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public PlayerState State;
|
||||
|
||||
/// <summary>
|
||||
/// 状态参数
|
||||
/// </summary>
|
||||
public StateEnterParams StateParams;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 玩家的物品
|
||||
/// </summary>
|
||||
public Dictionary<long, PlayerItem> Items = new Dictionary<long, PlayerItem>();
|
||||
|
||||
/// <summary>
|
||||
/// 当前手持物品id
|
||||
/// </summary>
|
||||
public long HandItemId;
|
||||
|
||||
/// <summary>
|
||||
/// 当前手持物品
|
||||
/// </summary>
|
||||
public PlayerItem HandItem => Items.GetValueOrDefault(HandItemId);
|
||||
|
||||
public List<Vector3> TrajectoryPoints = new List<Vector3>();
|
||||
|
||||
#region 初始化
|
||||
|
||||
public void InitPlayer(MapUnitInfo unitInfo)
|
||||
{
|
||||
PreviousState = PlayerState.None;
|
||||
State = PlayerState.Idle;
|
||||
AddComponent<PlayerView>();
|
||||
AddComponent<PlayerStateView>();
|
||||
if (unitInfo.Id == RoleModel.Instance.Id)
|
||||
{
|
||||
//自己
|
||||
AddComponent<PlayerInput>();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 物品
|
||||
|
||||
public void ReleaseItem(PlayerItem item)
|
||||
{
|
||||
if (Items.ContainsValue(item))
|
||||
{
|
||||
Items.Remove(item.Id);
|
||||
item.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void UnUseItem()
|
||||
{
|
||||
var prevItem = HandItem;
|
||||
HandItemId = 0;
|
||||
ItemChangeEvent(prevItem);
|
||||
}
|
||||
|
||||
public void UseItem(int configId, List<int> bindItems)
|
||||
{
|
||||
var prevItem = HandItem;
|
||||
var playerItemRod = Create<PlayerItem>(Scene);
|
||||
playerItemRod.Init(this, configId, bindItems);
|
||||
Items[playerItemRod.Id] = playerItemRod;
|
||||
HandItemId = playerItemRod.Id;
|
||||
ItemChangeEvent(prevItem);
|
||||
}
|
||||
|
||||
private void ItemChangeEvent(PlayerItem prevItem)
|
||||
{
|
||||
Scene.EventComponent.Publish(new PlayerItemChangeEvent
|
||||
{
|
||||
Player = this,
|
||||
Item = HandItem,
|
||||
PrevItem = prevItem
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 状态切换
|
||||
|
||||
/// <summary>
|
||||
/// 切换状态
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="stateParams"></param>
|
||||
public void ChangeState(PlayerState state, StateEnterParams stateParams = null)
|
||||
{
|
||||
if (state == State)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PreviousState = State;
|
||||
State = state;
|
||||
StateParams = stateParams;
|
||||
Scene.EventComponent.Publish(new PlayerStateChangeEvent
|
||||
{
|
||||
Player = this
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f7d8cb1b2cd4e25913e17e2b54e7ad9
|
||||
timeCreated: 1773036936
|
||||
@@ -1,239 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class StateParamsConst
|
||||
{
|
||||
public const string ChargedProgress = "ChargedProgress";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态进入参数(用于网络同步和动画/表现播放)
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class StateEnterParams
|
||||
{
|
||||
// 序列化友好的数据存储
|
||||
[SerializeField] private List<string> _keys = new();
|
||||
[SerializeField] private List<int> _intValues = new();
|
||||
[SerializeField] private List<float> _floatValues = new();
|
||||
[SerializeField] private List<Vector3> _vector3Values = new();
|
||||
[SerializeField] private List<Quaternion> _quaternionValues = new();
|
||||
|
||||
// 快速访问缓存
|
||||
private Dictionary<string, int> _intCache;
|
||||
private Dictionary<string, int> _floatCache;
|
||||
private Dictionary<string, int> _vector3Cache;
|
||||
private Dictionary<string, int> _quaternionCache;
|
||||
|
||||
public StateEnterParams()
|
||||
{
|
||||
InitializeCaches();
|
||||
}
|
||||
|
||||
private void InitializeCaches()
|
||||
{
|
||||
_intCache = new Dictionary<string, int>();
|
||||
_floatCache = new Dictionary<string, int>();
|
||||
_vector3Cache = new Dictionary<string, int>();
|
||||
_quaternionCache = new Dictionary<string, int>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空所有参数
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_keys.Clear();
|
||||
_intValues.Clear();
|
||||
_floatValues.Clear();
|
||||
_vector3Values.Clear();
|
||||
_quaternionValues.Clear();
|
||||
|
||||
_intCache.Clear();
|
||||
_floatCache.Clear();
|
||||
_vector3Cache.Clear();
|
||||
_quaternionCache.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 int 参数
|
||||
/// </summary>
|
||||
public void SetInt(string key, int value)
|
||||
{
|
||||
if (_intCache.TryGetValue(key, out int index))
|
||||
{
|
||||
_intValues[index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_keys.Add(key);
|
||||
_intValues.Add(value);
|
||||
_intCache[key] = _intValues.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 float 参数
|
||||
/// </summary>
|
||||
public void SetFloat(string key, float value)
|
||||
{
|
||||
if (_floatCache.TryGetValue(key, out int index))
|
||||
{
|
||||
_floatValues[index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_keys.Add(key);
|
||||
_floatValues.Add(value);
|
||||
_floatCache[key] = _floatValues.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 Vector3 参数
|
||||
/// </summary>
|
||||
public void SetVector3(string key, Vector3 value)
|
||||
{
|
||||
if (_vector3Cache.TryGetValue(key, out int index))
|
||||
{
|
||||
_vector3Values[index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_keys.Add(key);
|
||||
_vector3Values.Add(value);
|
||||
_vector3Cache[key] = _vector3Values.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 Quaternion 参数
|
||||
/// </summary>
|
||||
public void SetQuaternion(string key, Quaternion value)
|
||||
{
|
||||
if (_quaternionCache.TryGetValue(key, out int index))
|
||||
{
|
||||
_quaternionValues[index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_keys.Add(key);
|
||||
_quaternionValues.Add(value);
|
||||
_quaternionCache[key] = _quaternionValues.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 bool 参数
|
||||
/// </summary>
|
||||
public void SetBool(string key, bool value)
|
||||
{
|
||||
if (_intCache.TryGetValue(key, out int index))
|
||||
{
|
||||
_intValues[index] = value ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_keys.Add(key);
|
||||
_intValues.Add(value ? 1 : 0);
|
||||
_intCache[key] = _intValues.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 int 参数
|
||||
/// </summary>
|
||||
public int GetInt(string key, int defaultValue = 0)
|
||||
{
|
||||
if (_intCache.TryGetValue(key, out int index) && index < _intValues.Count)
|
||||
{
|
||||
return _intValues[index];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 float 参数
|
||||
/// </summary>
|
||||
public float GetFloat(string key, float defaultValue = 0f)
|
||||
{
|
||||
if (_floatCache.TryGetValue(key, out int index) && index < _floatValues.Count)
|
||||
{
|
||||
return _floatValues[index];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Vector3 参数
|
||||
/// </summary>
|
||||
public Vector3 GetVector3(string key, Vector3 defaultValue = default)
|
||||
{
|
||||
if (_vector3Cache.TryGetValue(key, out int index) && index < _vector3Values.Count)
|
||||
{
|
||||
return _vector3Values[index];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Quaternion 参数
|
||||
/// </summary>
|
||||
public Quaternion GetQuaternion(string key, Quaternion defaultValue = default)
|
||||
{
|
||||
if (_quaternionCache.TryGetValue(key, out int index) && index < _quaternionValues.Count)
|
||||
{
|
||||
return _quaternionValues[index];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 bool 参数
|
||||
/// </summary>
|
||||
public bool GetBool(string key, bool defaultValue = false)
|
||||
{
|
||||
if (_intCache.TryGetValue(key, out int index) && index < _intValues.Count)
|
||||
{
|
||||
return _intValues[index] == 1;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含某个参数
|
||||
/// </summary>
|
||||
public bool HasKey(string key)
|
||||
{
|
||||
return _intCache.ContainsKey(key) ||
|
||||
_floatCache.ContainsKey(key) ||
|
||||
_vector3Cache.ContainsKey(key) ||
|
||||
_quaternionCache.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制当前参数
|
||||
/// </summary>
|
||||
public StateEnterParams Clone()
|
||||
{
|
||||
var copy = new StateEnterParams
|
||||
{
|
||||
_keys = new List<string>(_keys),
|
||||
_intValues = new List<int>(_intValues),
|
||||
_floatValues = new List<float>(_floatValues),
|
||||
_vector3Values = new List<Vector3>(_vector3Values),
|
||||
_quaternionValues = new List<Quaternion>(_quaternionValues)
|
||||
};
|
||||
copy.InitializeCaches();
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0ff43bbc7dd46b387e62f574ceb2523
|
||||
timeCreated: 1773029210
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a348fcaa64274862baa542a3dc1ffc62
|
||||
timeCreated: 1773117606
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace NBF
|
||||
{
|
||||
public struct PlayerStateChangeEvent
|
||||
{
|
||||
public Player Player;
|
||||
}
|
||||
|
||||
|
||||
public struct PlayerItemChangeEvent
|
||||
{
|
||||
public Player Player;
|
||||
public PlayerItem Item;
|
||||
public PlayerItem PrevItem;
|
||||
}
|
||||
|
||||
public struct PlayerItemRodLingChangeEvent
|
||||
{
|
||||
public PlayerItem Item;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c10a4d3f5e354dc9a046ddf7219354b2
|
||||
timeCreated: 1773060354
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6965e70ae1742089580926e5b1adabf
|
||||
timeCreated: 1773037850
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7a71b6539c547fcaab2b89279530aef
|
||||
timeCreated: 1773116602
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab0e597ee4744959abdc5dc66546dacb
|
||||
timeCreated: 1777211780
|
||||
@@ -1,586 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NBC;
|
||||
// using Obi;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public enum LineType
|
||||
{
|
||||
Hand,
|
||||
HandDouble,
|
||||
Spinning,
|
||||
SpinningFloat,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 线模式
|
||||
/// </summary>
|
||||
public enum LineMode
|
||||
{
|
||||
Joint,
|
||||
Constraint
|
||||
}
|
||||
|
||||
public class FLine : FGearBase
|
||||
{
|
||||
public LineType LineType;
|
||||
|
||||
|
||||
[Header("连接点配置")] [SerializeField] private Transform anchorTransform;
|
||||
[SerializeField] private List<FLineLogicNode> lineNodes = new List<FLineLogicNode>();
|
||||
|
||||
|
||||
[Header("物理参数")] [SerializeField] private float positionCorrectionForce = 100f;
|
||||
[SerializeField] private float dampingCoefficient = 10f;
|
||||
[SerializeField] private int constraintIterations = 10;
|
||||
[SerializeField] private bool useMassWeighting = true;
|
||||
[SerializeField] private bool showDebugInfo = true;
|
||||
[Header("动态间距设置")] [SerializeField] private float defaultTransitionSpeed = 2f; // 默认长度变化速度(单位/秒)
|
||||
|
||||
private LineMode _lineMode = LineMode.Joint;
|
||||
// [SerializeField] private bool isLureConnect;
|
||||
//
|
||||
// [SerializeField] private RodLine rodLine;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 主线
|
||||
// /// </summary>
|
||||
// [SerializeField] private Rope fishingRope;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 浮漂和鱼钩线
|
||||
// /// </summary>
|
||||
// [SerializeField] private Rope bobberRope;
|
||||
|
||||
|
||||
// public LureController Lure;
|
||||
// public BobberController Bobber;
|
||||
//
|
||||
// public JointPinchController PinchController;
|
||||
|
||||
private readonly List<ConnectionConstraint> _constraints = new List<ConnectionConstraint>();
|
||||
|
||||
public FLineLogicNode StartNode { get; private set; }
|
||||
public FLineLogicNode BobberNode => GetNode(FLineLogicNodeType.Bobber);
|
||||
public FLineLogicNode EndNode { get; private set; }
|
||||
public LineMode LineMode => _lineMode;
|
||||
|
||||
|
||||
public float LinelenghtDiferent;
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class ConnectionConstraint
|
||||
{
|
||||
public FLineLogicNodeType NodeType;
|
||||
public Rigidbody bodyA;
|
||||
public Rigidbody bodyB;
|
||||
public float maxDistance;
|
||||
public float minDistance;
|
||||
public float currentDistance;
|
||||
public Vector3 direction;
|
||||
|
||||
// 动态目标距离(用于平滑过渡)
|
||||
public float targetMaxDistance;
|
||||
public bool hasPendingTransition;
|
||||
public bool hasPendingMaxTransition;
|
||||
public float maxTransitionSpeed;
|
||||
|
||||
public ConnectionConstraint(Rigidbody a, Rigidbody b, float maxDist, float minDist = 0f)
|
||||
{
|
||||
bodyA = a;
|
||||
bodyB = b;
|
||||
maxDistance = maxDist;
|
||||
minDistance = minDist;
|
||||
targetMaxDistance = maxDist;
|
||||
hasPendingTransition = false;
|
||||
hasPendingMaxTransition = false;
|
||||
maxTransitionSpeed = 0f;
|
||||
}
|
||||
|
||||
public void UpdateCurrentState()
|
||||
{
|
||||
if (bodyA && bodyB)
|
||||
{
|
||||
Vector3 delta = bodyB.position - bodyA.position;
|
||||
currentDistance = delta.magnitude;
|
||||
direction = currentDistance > 0.0001f ? delta.normalized : Vector3.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
if (anchorTransform == null)
|
||||
{
|
||||
var tipRb = Rod.Asset.LineConnectorRigidbody;
|
||||
|
||||
anchorTransform = tipRb.transform;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
BuildConstraints();
|
||||
StartNode = GetNode(FLineLogicNodeType.Start);
|
||||
EndNode = GetNode(FLineLogicNodeType.End);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
LinelenghtDiferent = GetLineDistance();
|
||||
|
||||
//非钓鱼状态
|
||||
if (Rod) Rod.PlayerItem.Tension = Mathf.Clamp(LinelenghtDiferent, 0f, 0.05f);
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
UpdateAnchorNode();
|
||||
FixedUpdateConstraints();
|
||||
}
|
||||
|
||||
public void ChangeMode(LineMode mode)
|
||||
{
|
||||
_lineMode = mode;
|
||||
|
||||
foreach (var fLineLogicNode in lineNodes)
|
||||
{
|
||||
fLineLogicNode.ChangeMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public List<FLineLogicNode> GetLineNodes()
|
||||
{
|
||||
return new List<FLineLogicNode>(lineNodes);
|
||||
}
|
||||
|
||||
public void Print()
|
||||
{
|
||||
// Log.Info($"当前线情况 TotalLength={TotalLength} CurrentStretchLength={CurrentStretchLength}");
|
||||
}
|
||||
|
||||
#region 连接点
|
||||
|
||||
private void UpdateAnchorNode()
|
||||
{
|
||||
if (anchorTransform == null || lineNodes.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var startNode = lineNodes[0].Rigidbody;
|
||||
startNode.transform.SetPositionAndRotation(anchorTransform.position, anchorTransform.rotation);
|
||||
|
||||
if (!startNode.isKinematic)
|
||||
{
|
||||
startNode.linearVelocity = Vector3.zero;
|
||||
startNode.angularVelocity = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个节点
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public FLineLogicNode GetNode(FLineLogicNodeType type)
|
||||
{
|
||||
foreach (var node in lineNodes)
|
||||
{
|
||||
if (node.NodeType == type)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetLenght(float lenght, FLineLogicNodeType type = FLineLogicNodeType.Bobber)
|
||||
{
|
||||
var node = GetNode(type);
|
||||
if (node != null)
|
||||
{
|
||||
if (_lineMode == LineMode.Joint)
|
||||
{
|
||||
node.SetLenght(lenght);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSegmentMaxLength(lenght, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 脚本约束
|
||||
|
||||
private void FixedUpdateConstraints()
|
||||
{
|
||||
if (_lineMode != LineMode.Constraint) return;
|
||||
if (!enabled || lineNodes.Count < 2) return;
|
||||
|
||||
// 更新动态过渡
|
||||
UpdateTransitions();
|
||||
|
||||
for (int iteration = 0; iteration < constraintIterations; iteration++)
|
||||
{
|
||||
ApplyDistanceConstraints();
|
||||
}
|
||||
|
||||
ApplyDamping();
|
||||
}
|
||||
|
||||
private void BuildConstraints()
|
||||
{
|
||||
_constraints.Clear();
|
||||
if (lineNodes.Count < 2) return;
|
||||
|
||||
// 创建约束
|
||||
for (int i = 0; i < lineNodes.Count - 1; i++)
|
||||
{
|
||||
FLineLogicNode currentNode = lineNodes[i];
|
||||
FLineLogicNode nextNode = lineNodes[i + 1];
|
||||
Rigidbody bodyA = currentNode ? currentNode.Rigidbody : null;
|
||||
Rigidbody bodyB = nextNode ? nextNode.Rigidbody : null;
|
||||
|
||||
if (bodyA != null && bodyB != null)
|
||||
{
|
||||
var constraint = new ConnectionConstraint(
|
||||
bodyA,
|
||||
bodyB,
|
||||
nextNode.Lenght
|
||||
);
|
||||
constraint.NodeType = nextNode.NodeType;
|
||||
_constraints.Add(constraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyDistanceConstraints()
|
||||
{
|
||||
for (int i = 0; i < _constraints.Count; i++)
|
||||
{
|
||||
var constraint = _constraints[i];
|
||||
if (!constraint.bodyA || !constraint.bodyB) continue;
|
||||
|
||||
constraint.UpdateCurrentState();
|
||||
|
||||
float currentDist = constraint.currentDistance;
|
||||
float maxDist = constraint.maxDistance;
|
||||
float minDist = constraint.minDistance;
|
||||
|
||||
float error = 0f;
|
||||
bool needCorrection = false;
|
||||
|
||||
if (currentDist > maxDist)
|
||||
{
|
||||
error = currentDist - maxDist;
|
||||
needCorrection = true;
|
||||
}
|
||||
|
||||
if (!needCorrection || Mathf.Abs(error) < 0.0001f) continue;
|
||||
|
||||
float invMassA = constraint.bodyA.isKinematic ? 0f : 1f / constraint.bodyA.mass;
|
||||
float invMassB = constraint.bodyB.isKinematic ? 0f : 1f / constraint.bodyB.mass;
|
||||
float totalInvMass = invMassA + invMassB;
|
||||
|
||||
if (totalInvMass < 0.0001f) continue;
|
||||
|
||||
float weightA = useMassWeighting ? (invMassA / totalInvMass) : 0.5f;
|
||||
float weightB = useMassWeighting ? (invMassB / totalInvMass) : 0.5f;
|
||||
|
||||
Vector3 correction = constraint.direction * error;
|
||||
Vector3 positionCorrectionA = correction * weightA;
|
||||
Vector3 positionCorrectionB = -correction * weightB;
|
||||
|
||||
constraint.bodyA.position += positionCorrectionA;
|
||||
constraint.bodyB.position += positionCorrectionB;
|
||||
|
||||
Vector3 velocityCorrectionA = positionCorrectionA / Time.fixedDeltaTime;
|
||||
Vector3 velocityCorrectionB = positionCorrectionB / Time.fixedDeltaTime;
|
||||
|
||||
constraint.bodyA.AddForce(velocityCorrectionA * constraint.bodyA.mass, ForceMode.Impulse);
|
||||
constraint.bodyB.AddForce(velocityCorrectionB * constraint.bodyB.mass, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyDamping()
|
||||
{
|
||||
for (int i = 0; i < _constraints.Count; i++)
|
||||
{
|
||||
var constraint = _constraints[i];
|
||||
if (!constraint.bodyA || !constraint.bodyB) continue;
|
||||
|
||||
if (constraint.currentDistance <= constraint.maxDistance) continue;
|
||||
|
||||
Vector3 relativeVelocity = constraint.bodyB.linearVelocity - constraint.bodyA.linearVelocity;
|
||||
float velocityInConstraintDir = Vector3.Dot(relativeVelocity, constraint.direction);
|
||||
|
||||
if (velocityInConstraintDir > 0)
|
||||
{
|
||||
float dampingForce = -velocityInConstraintDir * dampingCoefficient;
|
||||
Vector3 dampingImpulse = constraint.direction * dampingForce * Time.fixedDeltaTime;
|
||||
|
||||
constraint.bodyA.AddForce(-dampingImpulse * constraint.bodyA.mass, ForceMode.Impulse);
|
||||
constraint.bodyB.AddForce(dampingImpulse * constraint.bodyB.mass, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按速度过渡某段的最大距离
|
||||
/// </summary>
|
||||
private void SetSegmentMaxLength(float targetLength, FLineLogicNodeType type = FLineLogicNodeType.Bobber,
|
||||
float transitionSpeed = 2f)
|
||||
{
|
||||
var constraint = _constraints.Find(t => t.NodeType == type);
|
||||
if (constraint == null) return;
|
||||
|
||||
targetLength = Mathf.Max(0.01f, targetLength);
|
||||
float speed = Mathf.Max(0.01f, transitionSpeed > 0 ? transitionSpeed : defaultTransitionSpeed);
|
||||
|
||||
constraint.targetMaxDistance = targetLength;
|
||||
constraint.maxTransitionSpeed = speed;
|
||||
constraint.hasPendingMaxTransition = Mathf.Abs(constraint.maxDistance - targetLength) >= 0.0001f;
|
||||
constraint.hasPendingTransition = constraint.hasPendingMaxTransition;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 更新所有活跃的过渡
|
||||
/// </summary>
|
||||
private void UpdateTransitions()
|
||||
{
|
||||
float deltaTime = Time.fixedDeltaTime;
|
||||
|
||||
for (int i = 0; i < _constraints.Count; i++)
|
||||
{
|
||||
var constraint = _constraints[i];
|
||||
|
||||
if (constraint.hasPendingMaxTransition)
|
||||
{
|
||||
float nextMaxDistance = Mathf.MoveTowards(
|
||||
constraint.maxDistance,
|
||||
constraint.targetMaxDistance,
|
||||
constraint.maxTransitionSpeed * deltaTime
|
||||
);
|
||||
constraint.maxDistance = nextMaxDistance;
|
||||
var node = GetNode(constraint.NodeType);
|
||||
// SyncSegmentMaxLength(i, nextMaxDistance);
|
||||
node.SetLenght(nextMaxDistance);
|
||||
|
||||
if (Mathf.Abs(nextMaxDistance - constraint.targetMaxDistance) < 0.0001f)
|
||||
{
|
||||
constraint.maxDistance = constraint.targetMaxDistance;
|
||||
constraint.hasPendingMaxTransition = false;
|
||||
// SyncSegmentMaxLength(i, constraint.targetMaxDistance);
|
||||
node.SetLenght(constraint.targetMaxDistance);
|
||||
}
|
||||
}
|
||||
|
||||
constraint.hasPendingTransition = constraint.hasPendingMaxTransition;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取某个段是否正在进行过渡
|
||||
/// </summary>
|
||||
public bool IsSegmentTransitioning(int segmentIndex)
|
||||
{
|
||||
if (segmentIndex >= 0 && segmentIndex < _constraints.Count)
|
||||
{
|
||||
return _constraints[segmentIndex].hasPendingTransition;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// #region 极限判定
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 当前逻辑链总长度超出配置总长度的部分,小于等于零时记为 0。
|
||||
// /// </summary>
|
||||
// [Header("Limit Detection")]
|
||||
// public float CurrentStretchLength { get; private set; }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 总长度
|
||||
// /// </summary>
|
||||
// public float TotalLength { get; private set; }
|
||||
//
|
||||
// [Min(0f)]
|
||||
// // 极限判定的长度容差,允许链路在总长或单段长度上存在少量误差。
|
||||
// [SerializeField]
|
||||
// private float lengthLimitTolerance = 0.01f;
|
||||
//
|
||||
// [Min(0f)]
|
||||
// // 达到极限后,只有当前超长值大于该阈值时,才开始进入断线候选计时。
|
||||
// [SerializeField]
|
||||
// private float breakStretchThreshold = 0.3f;
|
||||
//
|
||||
// [Min(0f)]
|
||||
// // UI 百分比开始起算的最小超长值;低于或等于该值时统一按 0% 处理。
|
||||
// [SerializeField]
|
||||
// private float breakStretchPercentMinThreshold = 0.06f;
|
||||
//
|
||||
// [Min(0f)]
|
||||
// // 断线候选状态允许持续的最大时间;超过后会发出一次断线消息。
|
||||
// [SerializeField]
|
||||
// private float breakLimitDuration = 3f;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 当鱼线达到断线条件时发出的一次性消息。
|
||||
// /// 外部可订阅该事件,在回调中执行切线、播放表现或状态切换。
|
||||
// /// </summary>
|
||||
// public event Action<FLine> OnLineBreakRequested;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 当前是否处于极限状态。
|
||||
// /// 只要整链超出总长度容差,或任一逻辑段超出单段容差,即认为到达极限。
|
||||
// /// </summary>
|
||||
// public bool IsAtLimit { get; private set; }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 当前断线候选状态的累计时间。
|
||||
// /// 只有在处于极限状态,且 CurrentStretchLength 大于断线阈值时才会累加;否则重置为 0。
|
||||
// /// </summary>
|
||||
// public float LimitStateTime { get; private set; }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 当前极限断线消息是否已经发出过。
|
||||
// /// 在退出断线候选状态前只会发一次,避免重复通知。
|
||||
// /// </summary>
|
||||
// public bool HasBreakNotificationSent { get; private set; }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 当前拉力极限百分比。
|
||||
// /// 当超长值小于等于 breakStretchPercentMinThreshold 时为 0;
|
||||
// /// 当超长值大于等于 breakStretchThreshold 时为 100;
|
||||
// /// 中间区间按线性比例映射,供 UI 显示使用。
|
||||
// /// </summary>
|
||||
// public float CurrentBreakStretchPercent => EvaluateBreakStretchPercent(CurrentStretchLength);
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 当前是否正在进行断线候选计时。
|
||||
// /// </summary>
|
||||
// public bool IsBreakCountdownActive => IsAtLimit && CurrentStretchLength > breakStretchThreshold;
|
||||
//
|
||||
// private float EvaluateBreakStretchPercent(float stretchLength)
|
||||
// {
|
||||
// var percentMinThreshold = Mathf.Max(lengthLimitTolerance, breakStretchPercentMinThreshold);
|
||||
//
|
||||
// if (stretchLength <= percentMinThreshold)
|
||||
// {
|
||||
// return 0f;
|
||||
// }
|
||||
//
|
||||
// if (stretchLength >= breakStretchThreshold)
|
||||
// {
|
||||
// return 100f;
|
||||
// }
|
||||
//
|
||||
// if (breakStretchThreshold <= percentMinThreshold)
|
||||
// {
|
||||
// return 100f;
|
||||
// }
|
||||
//
|
||||
// return Mathf.InverseLerp(percentMinThreshold, breakStretchThreshold, stretchLength) * 100f;
|
||||
// }
|
||||
//
|
||||
// private void SetLimitState(bool isAtLimit)
|
||||
// {
|
||||
// IsAtLimit = isAtLimit;
|
||||
// }
|
||||
//
|
||||
// private void UpdateBreakCountdown(float deltaTime)
|
||||
// {
|
||||
// if (lineNodes.Count < 2)
|
||||
// {
|
||||
// SetLimitState(false);
|
||||
// ResetLimitState();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// var startNode = lineNodes[0];
|
||||
// var endNode = lineNodes[^1];
|
||||
// TotalLength = 0;
|
||||
// foreach (var node in lineNodes)
|
||||
// {
|
||||
// TotalLength += node.Lenght;
|
||||
// }
|
||||
//
|
||||
// var realLen = Vector3.Distance(startNode.transform.position, endNode.transform.position);
|
||||
// CurrentStretchLength = realLen - TotalLength;
|
||||
// if (CurrentStretchLength < 0f)
|
||||
// {
|
||||
// CurrentStretchLength = 0f;
|
||||
// }
|
||||
//
|
||||
// SetLimitState(CurrentStretchLength > lengthLimitTolerance);
|
||||
// if (LineMode != LineMode.Constraint) return;
|
||||
//
|
||||
// if (!IsBreakCountdownActive)
|
||||
// {
|
||||
// LimitStateTime = 0f;
|
||||
// HasBreakNotificationSent = false;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// LimitStateTime += Mathf.Max(0f, deltaTime);
|
||||
// if (HasBreakNotificationSent || LimitStateTime < breakLimitDuration)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// HasBreakNotificationSent = true;
|
||||
// NotifyLineBreakRequested();
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 发出鱼线达到断线条件的消息。
|
||||
// /// 这里预留给外部订阅,当前不在求解器内部直接执行断线逻辑。
|
||||
// /// </summary>
|
||||
// private void NotifyLineBreakRequested()
|
||||
// {
|
||||
// OnLineBreakRequested?.Invoke(this);
|
||||
// }
|
||||
//
|
||||
// private void ResetLimitState()
|
||||
// {
|
||||
// CurrentStretchLength = 0f;
|
||||
// IsAtLimit = false;
|
||||
// LimitStateTime = 0f;
|
||||
// HasBreakNotificationSent = false;
|
||||
// }
|
||||
//
|
||||
// #endregion
|
||||
|
||||
#region Tension
|
||||
|
||||
private float GetLineDistance()
|
||||
{
|
||||
//第一个节点到竿稍的位置-第一段鱼线长度
|
||||
return Vector3.Distance(StartNode.transform.position, BobberNode.transform.position) -
|
||||
BobberNode.Lenght;
|
||||
}
|
||||
|
||||
public float GetTension(float weight)
|
||||
{
|
||||
return weight * GetLineDistance();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0403ffd74ce46fab8bd4ef057e51432
|
||||
timeCreated: 1766582567
|
||||
@@ -1,102 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public enum FLineLogicNodeType
|
||||
{
|
||||
Start,
|
||||
Bobber,
|
||||
Weight,
|
||||
End
|
||||
}
|
||||
|
||||
public class FLineLogicNode : MonoBehaviour
|
||||
{
|
||||
[Header("节点设置")] public FLineLogicNodeType NodeType = FLineLogicNodeType.Bobber;
|
||||
[SerializeField] private Rope rope;
|
||||
[SerializeField] private Rigidbody preRigidbody;
|
||||
|
||||
private Rigidbody _rb;
|
||||
private SpringJoint _joint;
|
||||
private FLine _parentCable;
|
||||
|
||||
private float _lenght;
|
||||
|
||||
public Rigidbody PreRigidbody => preRigidbody;
|
||||
public Rigidbody Rigidbody => _rb;
|
||||
public FLine ParentCable => _parentCable;
|
||||
public SpringJoint Joint => _joint;
|
||||
|
||||
public float Lenght => _lenght;
|
||||
|
||||
public Rope Rope => rope;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rb = GetComponent<Rigidbody>();
|
||||
_parentCable = GetComponentInParent<FLine>();
|
||||
_joint = GetComponent<SpringJoint>();
|
||||
}
|
||||
|
||||
public void SetLenght(float lenght)
|
||||
{
|
||||
_lenght = lenght;
|
||||
if (_joint)
|
||||
{
|
||||
_joint.maxDistance = lenght;
|
||||
}
|
||||
|
||||
if (rope)
|
||||
{
|
||||
rope.SetTargetLength(lenght);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换约束模式
|
||||
/// </summary>
|
||||
/// <param name="mode"></param>
|
||||
public void ChangeMode(LineMode mode)
|
||||
{
|
||||
if (mode == LineMode.Joint)
|
||||
{
|
||||
if (_joint)
|
||||
{
|
||||
StartCoroutine(ReconnectedBody());
|
||||
}
|
||||
}
|
||||
else if (mode == LineMode.Constraint)
|
||||
{
|
||||
if (_joint) _joint.connectedBody = null;
|
||||
if (NodeType == FLineLogicNodeType.End)
|
||||
{
|
||||
Rigidbody.isKinematic = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator ReconnectedBody()
|
||||
{
|
||||
_joint.connectedBody = preRigidbody;
|
||||
yield return 1;
|
||||
Rigidbody.position = preRigidbody.position;
|
||||
preRigidbody.isKinematic = true;
|
||||
preRigidbody.linearVelocity = Vector3.zero;
|
||||
preRigidbody.angularVelocity = Vector3.zero;
|
||||
if (NodeType != FLineLogicNodeType.Start)
|
||||
{
|
||||
preRigidbody.isKinematic = false;
|
||||
}
|
||||
|
||||
yield return 1;
|
||||
preRigidbody.linearVelocity = Vector3.zero;
|
||||
preRigidbody.angularVelocity = Vector3.zero;
|
||||
if (NodeType == FLineLogicNodeType.End)
|
||||
{
|
||||
Rigidbody.isKinematic = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f840e1966fd4c2aafe2f37ca260cdd2
|
||||
timeCreated: 1777211794
|
||||
@@ -1,268 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 硬线系统测试脚本,直接读取 FLine 已配置的节点。
|
||||
/// </summary>
|
||||
public class FLineTest : MonoBehaviour
|
||||
{
|
||||
[Header("测试控制")] [SerializeField] private KeyCode fixMiddleKey = KeyCode.M;
|
||||
|
||||
[Header("动态间距控制")] [SerializeField] private KeyCode pullFirstKey = KeyCode.UpArrow;
|
||||
[SerializeField] private KeyCode relaxFirstKey = KeyCode.DownArrow;
|
||||
[SerializeField] private KeyCode fixedKey = KeyCode.F;
|
||||
[SerializeField] private KeyCode debugKey = KeyCode.D;
|
||||
[SerializeField, Min(0.01f)] private float extendAmount = 0.5f;
|
||||
[SerializeField, Min(0.01f)] private float holdAdjustSpeed = 1f;
|
||||
[SerializeField, Min(0.01f)] private float transitionSpeed = 2f;
|
||||
[SerializeField] private bool smoothTransition = true;
|
||||
|
||||
[SerializeField] private FLine line;
|
||||
private float[] initialLengths;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
extendAmount = Mathf.Max(0.01f, extendAmount);
|
||||
holdAdjustSpeed = Mathf.Max(0.01f, holdAdjustSpeed);
|
||||
transitionSpeed = Mathf.Max(0.01f, transitionSpeed);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
RefreshInitialLengths(true);
|
||||
line.SetLenght(0.2f);
|
||||
line.SetLenght(0.2f, FLineLogicNodeType.End);
|
||||
}
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!EnsureCable())
|
||||
return;
|
||||
|
||||
RefreshInitialLengths();
|
||||
HandleInput();
|
||||
|
||||
// if (line.CurrentBreakStretchPercent > 10f)
|
||||
// {
|
||||
// if (line.LineMode == LineMode.Constraint)
|
||||
// Debug.LogError(
|
||||
// $"当前极限情况,CurrentBreakStretchPercent={line.CurrentBreakStretchPercent} CurrentStretchLength={line.CurrentStretchLength} TotalLength={line.TotalLength} LimitStateTime={line.LimitStateTime}");
|
||||
// }
|
||||
}
|
||||
|
||||
private bool EnsureCable()
|
||||
{
|
||||
if (line)
|
||||
return true;
|
||||
|
||||
line = GetComponent<FLine>();
|
||||
return line != null;
|
||||
}
|
||||
|
||||
private List<FLineLogicNode> GetNodes()
|
||||
{
|
||||
return line != null ? line.GetLineNodes() : null;
|
||||
}
|
||||
|
||||
private void RefreshInitialLengths(bool force = false)
|
||||
{
|
||||
List<FLineLogicNode> nodes = GetNodes();
|
||||
int segmentCount = nodes != null ? Mathf.Max(0, nodes.Count - 1) : 0;
|
||||
|
||||
if (!force && initialLengths != null && initialLengths.Length == segmentCount)
|
||||
return;
|
||||
|
||||
initialLengths = new float[nodes.Count];
|
||||
|
||||
for (var i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
var node = nodes[i];
|
||||
initialLengths[i] = Mathf.Max(0.01f, node.Lenght);
|
||||
}
|
||||
}
|
||||
|
||||
private float GetCurrentMaxLength(int segmentIndex)
|
||||
{
|
||||
var nodes = line.GetLineNodes();
|
||||
var node = nodes[segmentIndex];
|
||||
// float length = line.GetSegmentMaxLength(segmentIndex);
|
||||
return Mathf.Max(0.01f, node.Lenght);
|
||||
}
|
||||
|
||||
private float GetTargetMaxLength(int segmentIndex)
|
||||
{
|
||||
var nodes = line.GetLineNodes();
|
||||
var node = nodes[segmentIndex];
|
||||
float length = node.Lenght;
|
||||
// if (length <= 0f)
|
||||
// length = line.GetSegmentMaxLength(segmentIndex);
|
||||
|
||||
return Mathf.Max(0.01f, length);
|
||||
}
|
||||
|
||||
private int GetSegmentCount()
|
||||
{
|
||||
return initialLengths != null ? initialLengths.Length : 0;
|
||||
}
|
||||
|
||||
private void HandleInput()
|
||||
{
|
||||
HandleOriginalControls();
|
||||
HandleDynamicDistanceControls();
|
||||
}
|
||||
|
||||
private void HandleOriginalControls()
|
||||
{
|
||||
List<FLineLogicNode> nodes = GetNodes();
|
||||
if (nodes == null)
|
||||
return;
|
||||
|
||||
if (Input.GetKeyDown(fixMiddleKey) && nodes.Count >= 3)
|
||||
{
|
||||
int middleIndex = nodes.Count / 2;
|
||||
FLineLogicNode middleNode = nodes[middleIndex];
|
||||
Rigidbody middleRb = middleNode ? middleNode.Rigidbody : null;
|
||||
|
||||
if (middleNode && middleRb)
|
||||
{
|
||||
bool newState = !middleRb.isKinematic;
|
||||
Debug.Log($"中间节点({middleIndex}) {(newState ? "固定" : "释放")} - 观察其他节点变化");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDynamicDistanceControls()
|
||||
{
|
||||
if (line == null || initialLengths == null || initialLengths.Length == 0)
|
||||
return;
|
||||
|
||||
if (Input.GetKeyDown(pullFirstKey))
|
||||
PullFirstSegment(extendAmount * 0.5f);
|
||||
|
||||
if (Input.GetKeyDown(relaxFirstKey))
|
||||
RelaxFirstSegment(extendAmount * 0.5f);
|
||||
|
||||
if (Input.GetKeyDown(fixedKey))
|
||||
{
|
||||
if (line.LineMode == LineMode.Joint) line.ChangeMode(LineMode.Constraint);
|
||||
else line.ChangeMode(LineMode.Joint);
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(debugKey))
|
||||
{
|
||||
line.Print();
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplySegmentTargetLength(FLineLogicNodeType type, float targetLength)
|
||||
{
|
||||
line.SetLenght(targetLength, type);
|
||||
}
|
||||
|
||||
private void PullFirstSegment(float amount)
|
||||
{
|
||||
if (GetSegmentCount() <= 0)
|
||||
return;
|
||||
|
||||
float targetLength = Mathf.Max(0.1f, GetTargetMaxLength(0) - amount);
|
||||
ApplySegmentTargetLength(0, targetLength);
|
||||
Debug.Log($"拉紧第一段到 {targetLength:F2}");
|
||||
}
|
||||
|
||||
private void RelaxFirstSegment(float amount)
|
||||
{
|
||||
if (GetSegmentCount() <= 0)
|
||||
return;
|
||||
|
||||
float targetLength = GetTargetMaxLength(0) + amount;
|
||||
ApplySegmentTargetLength(0, targetLength);
|
||||
Debug.Log($"放松第一段到 {targetLength:F2}");
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (!EnsureCable())
|
||||
return;
|
||||
|
||||
RefreshInitialLengths();
|
||||
|
||||
List<FLineLogicNode> nodes = GetNodes();
|
||||
int nodeCount = nodes != null ? nodes.Count : 0;
|
||||
|
||||
GUILayout.BeginArea(new Rect(10f, 10f, 360f, 260f));
|
||||
GUILayout.Label("=== 硬线系统测试控制 ===");
|
||||
GUILayout.Label("原始控制:");
|
||||
GUILayout.Label($" {fixMiddleKey} - 固定/释放中间节点");
|
||||
GUILayout.Space(10f);
|
||||
GUILayout.Label("动态间距控制:");
|
||||
GUILayout.Label($" {pullFirstKey} - 拉紧第一段");
|
||||
GUILayout.Label($" {relaxFirstKey} - 放松第一段");
|
||||
GUILayout.Label(" Shift+滚轮 - 调整最近段");
|
||||
GUILayout.Space(10f);
|
||||
GUILayout.Label("设置:");
|
||||
GUILayout.Label($" 节点数: {nodeCount}");
|
||||
GUILayout.Label(" 初始长度来源: FLine 节点配置");
|
||||
GUILayout.Label($" 过渡模式: {(smoothTransition ? "平滑" : "即时")}");
|
||||
if (smoothTransition)
|
||||
GUILayout.Label($" 过渡速度: {transitionSpeed:F1}");
|
||||
|
||||
GUILayout.EndArea();
|
||||
|
||||
GUILayout.BeginArea(new Rect(10f, 280f, 360f, 220f));
|
||||
GUILayout.Label("=== 各段实际长度 ===");
|
||||
|
||||
// for (int i = 0; i < Mathf.Min(GetSegmentCount(), 10); i++)
|
||||
// {
|
||||
// Rigidbody bodyA = nodes[i] ? nodes[i].Rigidbody : null;
|
||||
// Rigidbody bodyB = nodes[i + 1] ? nodes[i + 1].Rigidbody : null;
|
||||
// if (!bodyA || !bodyB)
|
||||
// continue;
|
||||
//
|
||||
// float actualDistance = Vector3.Distance(bodyA.position, bodyB.position);
|
||||
// float currentLimit = GetCurrentMaxLength(i);
|
||||
// float targetLimit = GetTargetMaxLength(i);
|
||||
//
|
||||
// string segmentInfo = $"段{i}: {actualDistance:F2} (限制: {currentLimit:F2}";
|
||||
// if (line.IsSegmentTransitioning(i))
|
||||
// segmentInfo += $" -> {targetLimit:F2}";
|
||||
//
|
||||
// segmentInfo += ")";
|
||||
//
|
||||
// if (actualDistance > targetLimit * 1.1f)
|
||||
// {
|
||||
// GUI.color = Color.red;
|
||||
// }
|
||||
// else if (line.IsSegmentTransitioning(i))
|
||||
// {
|
||||
// GUI.color = Color.yellow;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// GUI.color = Color.green;
|
||||
// }
|
||||
//
|
||||
// GUILayout.Label(segmentInfo);
|
||||
// }
|
||||
|
||||
GUI.color = Color.white;
|
||||
|
||||
bool anyTransitioning = false;
|
||||
for (int i = 0; i < GetSegmentCount(); i++)
|
||||
{
|
||||
if (line.IsSegmentTransitioning(i))
|
||||
{
|
||||
anyTransitioning = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyTransitioning)
|
||||
GUILayout.Label("状态: 过渡中...");
|
||||
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 535734a3b6eb4e16847b2fc9d9dee1c3
|
||||
timeCreated: 1777263325
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 958b50133e064daf9764313f24b892da
|
||||
timeCreated: 1773069791
|
||||
@@ -1,15 +0,0 @@
|
||||
using Fantasy.Event;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class OnPlayerItemRodLingChangeEvent: EventSystem<PlayerItemRodLingChangeEvent>
|
||||
{
|
||||
protected override void Handler(PlayerItemRodLingChangeEvent self)
|
||||
{
|
||||
var itemView = self.Item.GetComponent<PlayerItemView>();
|
||||
itemView.Rod.SetLineLength();
|
||||
// var view = self.Player.GetOrAddComponent<PlayerView>();
|
||||
// view.ChangeItem(self).Coroutine();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 308a4c63d4da4a5e83db7426790c9b6e
|
||||
timeCreated: 1773155866
|
||||
@@ -1,13 +0,0 @@
|
||||
using Fantasy.Event;
|
||||
|
||||
namespace NBF.Handle
|
||||
{
|
||||
public class OnPlayerStateChangeEvent : EventSystem<PlayerItemChangeEvent>
|
||||
{
|
||||
protected override void Handler(PlayerItemChangeEvent self)
|
||||
{
|
||||
var view = self.Player.GetOrAddComponent<PlayerView>();
|
||||
view.ChangeItem(self).Coroutine();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5897acb7a6e40fcb3123362df1669f3
|
||||
timeCreated: 1773069799
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f9c361f2958454abb43724693a2157a
|
||||
timeCreated: 1773116527
|
||||
@@ -1,28 +0,0 @@
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Entitas;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 玩家物品视图组件
|
||||
/// </summary>
|
||||
public class PlayerItemView : Entity
|
||||
{
|
||||
public PlayerItem Item { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 竿子
|
||||
/// </summary>
|
||||
public FRod Rod { get; private set; }
|
||||
|
||||
public async FTask InitShow(PlayerItem item)
|
||||
{
|
||||
Item = item;
|
||||
var itemConfig = Game.Tables.TbItem.Get(Item.ConfigID);
|
||||
Rod = itemConfig.InstantiateAndComponent<FRod>(SceneSettings.Instance.GearNode, Vector3.zero,
|
||||
Quaternion.identity);
|
||||
await Rod.InitRod(Item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98838cf2cf934b8aaaf97f4d58544055
|
||||
timeCreated: 1773116536
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c38d17daa1164359ad9f9466be692b7c
|
||||
timeCreated: 1773038185
|
||||
@@ -1,98 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class JointPinchController : MonoBehaviour
|
||||
{
|
||||
// 配置参数
|
||||
[SerializeField] private float moveSpeed = 5f;
|
||||
[SerializeField] private float snapDistance = 0.1f;
|
||||
|
||||
private FixedJoint pinchJoint;
|
||||
private Rigidbody rb;
|
||||
|
||||
|
||||
private float maxCatchupDuration = 0.5f;
|
||||
private Transform targetTransform;
|
||||
private float originalSpring;
|
||||
private float pinchElapsedTime;
|
||||
|
||||
|
||||
public bool isPinched { get; private set; }
|
||||
|
||||
private bool moveToTargetDone;
|
||||
private float _speed;
|
||||
|
||||
void Start()
|
||||
{
|
||||
rb = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
if (isPinched && !moveToTargetDone && targetTransform != null)
|
||||
{
|
||||
pinchElapsedTime += Time.fixedDeltaTime;
|
||||
transform.position =
|
||||
Vector3.MoveTowards(transform.position, targetTransform.position, Time.deltaTime * _speed);
|
||||
if (Vector3.Distance(transform.position, targetTransform.position) < 0.1f ||
|
||||
pinchElapsedTime >= maxCatchupDuration)
|
||||
{
|
||||
moveToTargetDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
// SyncPosition();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
SyncPosition();
|
||||
}
|
||||
|
||||
private void SyncPosition()
|
||||
{
|
||||
if (!isPinched) return;
|
||||
if (!moveToTargetDone) return;
|
||||
transform.position = targetTransform.position;
|
||||
}
|
||||
|
||||
// 外部调用:开始捏住流程
|
||||
public void StartPinch(Transform fingerTransform, float speed = 3, float _maxCatchupDuration = 0.3f)
|
||||
{
|
||||
_speed = speed;
|
||||
Rigidbody fingerRb = fingerTransform.GetComponent<Rigidbody>();
|
||||
if (fingerRb == null)
|
||||
{
|
||||
Debug.LogError("目标必须带有Rigidbody");
|
||||
return;
|
||||
}
|
||||
|
||||
maxCatchupDuration = _maxCatchupDuration;
|
||||
pinchElapsedTime = 0f;
|
||||
isPinched = true;
|
||||
rb.useGravity = false;
|
||||
rb.isKinematic = true;
|
||||
moveToTargetDone = false;
|
||||
targetTransform = fingerTransform;
|
||||
}
|
||||
|
||||
|
||||
// 外部调用:释放捏住
|
||||
public void ReleasePinch()
|
||||
{
|
||||
isPinched = false;
|
||||
rb.useGravity = true;
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
rb.isKinematic = false;
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
targetTransform = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1de1bec90e454664a860c5248170ff95
|
||||
timeCreated: 1773588197
|
||||
@@ -1,184 +0,0 @@
|
||||
using System;
|
||||
using KINEMATION.MagicBlend.Runtime;
|
||||
using NBC;
|
||||
using NBF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerAnimator : PlayerMonoBehaviour
|
||||
{
|
||||
public Animator _Animator;
|
||||
|
||||
private bool _isRodLayerEnabled;
|
||||
private bool _isInit;
|
||||
private PlayerIK _IK;
|
||||
private MagicBlending _magicBlending;
|
||||
private bool _IsInVehicle;
|
||||
|
||||
#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 OnGroundHash = Animator.StringToHash("OnGround");
|
||||
public static readonly int PrepareThrowHash = Animator.StringToHash("PrepareThrow");
|
||||
public static readonly int StartThrowHash = Animator.StringToHash("StartThrow");
|
||||
public static readonly int BaitThrownHash = Animator.StringToHash("BaitThrown");
|
||||
private static readonly int FishingUpHash = Animator.StringToHash("FishingUp");
|
||||
|
||||
public static readonly string LureRodLayer = "LureRod";
|
||||
public static readonly string HandRodLayer = "HandRod";
|
||||
|
||||
|
||||
public float FishingUp
|
||||
{
|
||||
get => _Animator.GetFloat(FishingUpHash);
|
||||
set => _Animator.SetFloat(FishingUpHash, value);
|
||||
}
|
||||
|
||||
public bool OnGround
|
||||
{
|
||||
get => _Animator.GetBool(OnGroundHash);
|
||||
set => _Animator.SetBool(OnGroundHash, value);
|
||||
}
|
||||
|
||||
public bool StartThrow
|
||||
{
|
||||
get => _Animator.GetBool(StartThrowHash);
|
||||
set => _Animator.SetBool(StartThrowHash, value);
|
||||
}
|
||||
|
||||
public bool BaitThrown
|
||||
{
|
||||
get => _Animator.GetBool(BaitThrownHash);
|
||||
set => _Animator.SetBool(BaitThrownHash, value);
|
||||
}
|
||||
|
||||
public bool PrepareThrow
|
||||
{
|
||||
get => _Animator.GetBool(PrepareThrowHash);
|
||||
set => _Animator.SetBool(PrepareThrowHash, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
protected override void OnAwake()
|
||||
{
|
||||
_magicBlending = GetComponent<MagicBlending>();
|
||||
_Animator = GetComponent<Animator>();
|
||||
_Animator.keepAnimatorStateOnDisable = true;
|
||||
_IK = GetComponent<PlayerIK>();
|
||||
_isInit = true;
|
||||
}
|
||||
|
||||
|
||||
public void OnUnUseItem()
|
||||
{
|
||||
_isRodLayerEnabled = false;
|
||||
}
|
||||
|
||||
|
||||
public void OnUseItem(PlayerItemView item)
|
||||
{
|
||||
var itemType = item.Item.ConfigID.GetItemType();
|
||||
if (itemType == ItemType.Rod)
|
||||
{
|
||||
_isRodLayerEnabled = true;
|
||||
// _IK.SetBipedLeftHandIK(enabled: false, reel.FingersIKAnchor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetLayerWeight(string layer, float weight)
|
||||
{
|
||||
_Animator.SetLayerWeight(_Animator.GetLayerIndex(layer), weight);
|
||||
}
|
||||
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
{
|
||||
float value3 = Mathf.Lerp(_Animator.GetFloat(Forward), Player.Speed / 5f,
|
||||
Time.deltaTime * 20f);
|
||||
float value4 = Mathf.Lerp(_Animator.GetFloat(Turn), Player.RotationSpeed,
|
||||
Time.deltaTime * 15f);
|
||||
_Animator.SetFloat(Forward, Mathf.Clamp01(value3));
|
||||
_Animator.SetFloat(Turn, Mathf.Clamp(value4, -1f, 1f));
|
||||
}
|
||||
|
||||
|
||||
_Animator.SetBool(OnGroundHash, _IsInVehicle || Player.IsGrounded);
|
||||
|
||||
|
||||
var isHandRodLayerEnabled = _isRodLayerEnabled && !Player.IsLureRod ? 1 : 0;
|
||||
|
||||
float handRodLayerWeight = _Animator.GetLayerWeight(_Animator.GetLayerIndex(HandRodLayer));
|
||||
SetLayerWeight(HandRodLayer,
|
||||
Mathf.MoveTowards(handRodLayerWeight, isHandRodLayerEnabled, Time.deltaTime * 3f));
|
||||
|
||||
|
||||
var isLureRodLayerEnabled = _isRodLayerEnabled && Player.IsLureRod ? 1 : 0;
|
||||
float lureRodLayerWeight = _Animator.GetLayerWeight(_Animator.GetLayerIndex(LureRodLayer));
|
||||
SetLayerWeight(LureRodLayer,
|
||||
Mathf.MoveTowards(lureRodLayerWeight, isLureRodLayerEnabled, Time.deltaTime * 3f));
|
||||
}
|
||||
|
||||
#region 动画事件
|
||||
|
||||
/// <summary>
|
||||
/// 抬杆到底动画事件
|
||||
/// </summary>
|
||||
public void OnRodPowerUp()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始抛出动画事件
|
||||
/// </summary>
|
||||
public void OnRodThrowStart()
|
||||
{
|
||||
Debug.LogError("OnRodThrowStart");
|
||||
if (Player.State == PlayerState.Throw)
|
||||
{
|
||||
var playerStateView = Player.GetComponent<PlayerStateView>();
|
||||
if (playerStateView.CurrentStateView is PlayerStageViewThrow playerStateThrow)
|
||||
{
|
||||
playerStateThrow.OnRodThrowStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 抛竿结束动画事件
|
||||
/// </summary>
|
||||
public void OnRodThrownEnd()
|
||||
{
|
||||
Debug.LogError("OnRodThrownEnd");
|
||||
if (Player.State == PlayerState.Throw)
|
||||
{
|
||||
var playerStateView = Player.GetComponent<PlayerStateView>();
|
||||
if (playerStateView.CurrentStateView is PlayerStageViewThrow playerStateThrow)
|
||||
{
|
||||
playerStateThrow.OnRodThrownEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fc336a939c4416db623f3b4ae855265
|
||||
timeCreated: 1766470716
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerArm : PlayerMonoBehaviour
|
||||
{
|
||||
public bool FixLowerArm;
|
||||
public bool IsLeft;
|
||||
public LimbIK IK;
|
||||
public Transform LowerArm;
|
||||
public Transform RodContainer;
|
||||
public FingerRig FingerRig;
|
||||
|
||||
|
||||
[HideInInspector] public float interactionTargetWeight;
|
||||
|
||||
private const int MaxFixEyeAngle = 15;
|
||||
|
||||
protected override void OnAwake()
|
||||
{
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01ef40348d8b4d4da250acf0a921fc2a
|
||||
timeCreated: 1768660096
|
||||
@@ -1,24 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerChest : PlayerMonoBehaviour
|
||||
{
|
||||
private const int MaxFixEyeAngle = 15;
|
||||
private const int MinFixEyeAngle = -10;
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
FixArmAngle();
|
||||
}
|
||||
|
||||
private void FixArmAngle()
|
||||
{
|
||||
var angle = Player.EyeAngle;
|
||||
if (angle > MaxFixEyeAngle) angle = MaxFixEyeAngle;
|
||||
else if (angle < MinFixEyeAngle) angle = MinFixEyeAngle;
|
||||
var val = transform.localEulerAngles;
|
||||
transform.localEulerAngles = new Vector3(val.x, val.y, val.z - angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e152a74e74b54d17ace5403a1570e12a
|
||||
timeCreated: 1768668096
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerDebug : PlayerMonoBehaviour
|
||||
{
|
||||
private void Update()
|
||||
{
|
||||
DrawLastTrajectory();
|
||||
}
|
||||
|
||||
private void DrawLastTrajectory()
|
||||
{
|
||||
if (Player == null) return;
|
||||
|
||||
|
||||
for (int i = 1; i < Player.TrajectoryPoints.Count; i++)
|
||||
{
|
||||
Debug.DrawLine(Player.TrajectoryPoints[i - 1], Player.TrajectoryPoints[i], Color.yellow);
|
||||
}
|
||||
|
||||
// Debug.DrawRay(Player.TrajectoryPoints[Player.TrajectoryPoints.Count], Vector3.up * 0.3f, Color.cyan);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fe64f6594c24eef9fbaf147754871f8
|
||||
timeCreated: 1774445468
|
||||
@@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerIK : PlayerMonoBehaviour
|
||||
{
|
||||
public enum UpdateType
|
||||
{
|
||||
Update = 0,
|
||||
FixedUpdate = 1,
|
||||
LateUpdate = 2,
|
||||
Default = 3
|
||||
}
|
||||
|
||||
public UpdateType UpdateSelected;
|
||||
|
||||
private LookAtIK _LookAtIK;
|
||||
|
||||
[SerializeField] private float transitionWeightTimeScale = 1f;
|
||||
|
||||
protected override void OnAwake()
|
||||
{
|
||||
_LookAtIK = GetComponent<LookAtIK>();
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
_LookAtIK.UpdateSolverExternal();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb36ecc5b1784d948837600cf18808cd
|
||||
timeCreated: 1765121426
|
||||
@@ -1,22 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public abstract class PlayerMonoBehaviour : MonoBehaviour
|
||||
{
|
||||
public Player Player { get; private set; }
|
||||
|
||||
public PlayerUnityComponent UnityComponent { get; private set; }
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
UnityComponent = GetComponentInParent<PlayerUnityComponent>();
|
||||
Player = UnityComponent.Player;
|
||||
OnAwake();
|
||||
}
|
||||
|
||||
protected virtual void OnAwake()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fbde40efe5345cd8c05ea6c1f1914cf
|
||||
timeCreated: 1773040970
|
||||
@@ -1,25 +0,0 @@
|
||||
using ECM2;
|
||||
using ECM2.Examples.FirstPerson;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerUnityComponent : MonoBehaviour
|
||||
{
|
||||
public Player Player { get; set; }
|
||||
public Transform Root;
|
||||
public Transform Eye;
|
||||
public Transform FppLook;
|
||||
public Transform IK;
|
||||
public PlayerModelAsset ModelAsset;
|
||||
public CharacterMovement Character;
|
||||
public FirstPersonCharacter FirstPerson;
|
||||
|
||||
[Header("视角相关")] public float MouseSensitivity = 0.1f;
|
||||
[Space(15f)] public bool invertLook = true;
|
||||
|
||||
public float minPitch = -60f;
|
||||
|
||||
public float maxPitch = 60f;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a25908f34e4e4464a922b88337a5b733
|
||||
timeCreated: 1773038189
|
||||
@@ -1,225 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerInput : Entity
|
||||
{
|
||||
public Player Player { get; private set; }
|
||||
public PlayerView View { get; private set; }
|
||||
|
||||
#region 生命周期
|
||||
|
||||
public class PlayerViewAwakeSystem : AwakeSystem<PlayerInput>
|
||||
{
|
||||
protected override void Awake(PlayerInput self)
|
||||
{
|
||||
self.Player = self.GetParent<Player>();
|
||||
self.View = self.Player.GetComponent<PlayerView>();
|
||||
self.AddInputEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerViewUpdateSystem : UpdateSystem<PlayerInput>
|
||||
{
|
||||
protected override void Update(PlayerInput self)
|
||||
{
|
||||
self.UpdateInput();
|
||||
self.UpdateMove();
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerViewDestroySystem : DestroySystem<PlayerInput>
|
||||
{
|
||||
protected override void Destroy(PlayerInput self)
|
||||
{
|
||||
self.RemoveInputEvent();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Input
|
||||
|
||||
private void UpdateInput()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Alpha0))
|
||||
{
|
||||
// SetLineLength(lineLength);
|
||||
}
|
||||
else if (Input.GetKeyDown(KeyCode.Plus) || Input.GetKeyDown(KeyCode.Equals))
|
||||
{
|
||||
Player.HandItem.LineLength += 0.1f;
|
||||
// lineLength += 0.1f;
|
||||
// SetLineLength(lineLength);
|
||||
}
|
||||
else if (Input.GetKeyDown(KeyCode.Minus))
|
||||
{
|
||||
Player.HandItem.LineLength -= 0.1f;
|
||||
// lineLength -= 0.1f;
|
||||
// SetLineLength(lineLength);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddInputEvent()
|
||||
{
|
||||
InputManager.OnPlayerPerformed += OnPlayerCanceled;
|
||||
InputManager.OnPlayerPerformed += OnPlayerPerformed;
|
||||
|
||||
InputManager.OnPlayerValueCanceled += OnPlayerValueCanceled;
|
||||
InputManager.OnPlayerValuePerformed += OnPlayerValuePerformed;
|
||||
}
|
||||
|
||||
private void RemoveInputEvent()
|
||||
{
|
||||
InputManager.OnPlayerPerformed += OnPlayerCanceled;
|
||||
InputManager.OnPlayerPerformed += OnPlayerPerformed;
|
||||
|
||||
InputManager.OnPlayerValueCanceled += OnPlayerValueCanceled;
|
||||
InputManager.OnPlayerValuePerformed += OnPlayerValuePerformed;
|
||||
}
|
||||
|
||||
private void OnPlayerPerformed(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Player.Run = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerCanceled(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Player.Run = false;
|
||||
}
|
||||
else if (action == InputDef.Player.ToBag)
|
||||
{
|
||||
//取消手持物品
|
||||
Log.Info($"取消手持物品");
|
||||
Player.UnUseItem();
|
||||
// Game.Instance.StartCoroutine(UnUseItem());
|
||||
}
|
||||
else if (action.StartsWith(InputDef.Player.QuickStarts))
|
||||
{
|
||||
var index = int.Parse(action.Replace(InputDef.Player.QuickStarts, string.Empty));
|
||||
Log.Info($"快速使用===={index}");
|
||||
var item = RoleModel.Instance.GetSlotItem(index - 1);
|
||||
if (item != null)
|
||||
{
|
||||
List<ItemInfo> children = RoleModel.Instance.GetBindItems(item.Id);
|
||||
List<int> bindItems = children.Select(itemInfo => itemInfo.ConfigId).ToList();
|
||||
Player.UseItem(item.ConfigId, bindItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValueCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
var actionName = context.action.name;
|
||||
if (actionName == InputDef.Player.Move)
|
||||
{
|
||||
Player.MoveInput = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValuePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
var actionName = context.action.name;
|
||||
if (actionName == InputDef.Player.Move)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
Player.MoveInput = v2;
|
||||
}
|
||||
else if (actionName == InputDef.Player.Look)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Move
|
||||
|
||||
private Quaternion _lastRotation;
|
||||
|
||||
private void UpdateMove()
|
||||
{
|
||||
UpdateGrounded();
|
||||
ProcessMoveStates();
|
||||
UpdateLookInput();
|
||||
}
|
||||
|
||||
private void ProcessMoveStates()
|
||||
{
|
||||
{
|
||||
var num2 = Player.Run ? 7 : 5;
|
||||
Vector3 vector2 = View.Unity.FirstPerson.GetRightVector() * Player.MoveInput.x * num2;
|
||||
vector2 += View.Unity.FirstPerson.GetForwardVector() * Player.MoveInput.y * num2;
|
||||
// if (checkWaterBound)
|
||||
// {
|
||||
// SetMovementDirectionWithRaycastCheck(vector2);
|
||||
// }
|
||||
// else
|
||||
{
|
||||
View.Unity.FirstPerson.SetMovementDirection(vector2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGrounded()
|
||||
{
|
||||
Player.IsGrounded = View.Unity.FirstPerson.IsGrounded();
|
||||
Player.Speed = View.Unity.FirstPerson.velocity.magnitude;
|
||||
|
||||
Quaternion rotation = View.Unity.FirstPerson.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);
|
||||
|
||||
|
||||
Player.RotationSpeed = turnValue;
|
||||
|
||||
_lastRotation = rotation;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Look
|
||||
|
||||
private void UpdateLookInput()
|
||||
{
|
||||
Vector2 value = InputManager.GetLookInput();
|
||||
var u3d = View.Unity;
|
||||
u3d.FirstPerson.AddControlYawInput(value.x * u3d.MouseSensitivity);
|
||||
u3d.FirstPerson.AddControlPitchInput((u3d.invertLook ? 0f - value.y : value.y) * u3d.MouseSensitivity,
|
||||
u3d.minPitch, u3d.maxPitch);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d74cb6e741243478aeb0a3053211fcd
|
||||
timeCreated: 1773039193
|
||||
@@ -1,81 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Event;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态显示层组件
|
||||
/// </summary>
|
||||
public class PlayerStateView : Entity
|
||||
{
|
||||
private readonly Dictionary<PlayerState, PlayerStageViewBase> _stageViews =
|
||||
new Dictionary<PlayerState, PlayerStageViewBase>();
|
||||
|
||||
private PlayerStageViewBase _currentStateView;
|
||||
private Player _player;
|
||||
|
||||
public PlayerStageViewBase CurrentStateView => _currentStateView;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
_player = GetParent<Player>();
|
||||
_stageViews.Add(PlayerState.Idle, new PlayerStageViewIdle());
|
||||
_stageViews.Add(PlayerState.Prepare, new PlayerStageViewPrepare());
|
||||
_stageViews.Add(PlayerState.Throw, new PlayerStageViewThrow());
|
||||
_stageViews.Add(PlayerState.Fishing, new PlayerStageViewFishing());
|
||||
_stageViews.Add(PlayerState.Fight, new PlayerStageViewFight());
|
||||
foreach (var playerStageView in _stageViews.Values)
|
||||
{
|
||||
playerStageView.Init(_player);
|
||||
}
|
||||
|
||||
OnStageChange();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
_currentStateView?.Update();
|
||||
}
|
||||
|
||||
public void OnStageChange()
|
||||
{
|
||||
if (_currentStateView != null)
|
||||
{
|
||||
_currentStateView.Exit();
|
||||
}
|
||||
|
||||
_currentStateView = _stageViews.GetValueOrDefault(_player.State);
|
||||
_currentStateView?.Enter(_player.StateParams, _player.PreviousState);
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerStateViewComponentAwakeSystem : AwakeSystem<PlayerStateView>
|
||||
{
|
||||
protected override void Awake(PlayerStateView self)
|
||||
{
|
||||
self.Awake();
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerStateViewComponentUpdateSystem : UpdateSystem<PlayerStateView>
|
||||
{
|
||||
protected override void Update(PlayerStateView self)
|
||||
{
|
||||
self.Update();
|
||||
}
|
||||
}
|
||||
|
||||
public class OnPlayerStageChange : EventSystem<PlayerStateChangeEvent>
|
||||
{
|
||||
protected override void Handler(PlayerStateChangeEvent self)
|
||||
{
|
||||
var stateView = self.Player.GetComponent<PlayerStateView>();
|
||||
if (stateView != null)
|
||||
{
|
||||
stateView.OnStageChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f48ea2ea6a0e4b38aa97a3fd07f3a6cc
|
||||
timeCreated: 1773060520
|
||||
@@ -1,156 +0,0 @@
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using NBF.Fishing2;
|
||||
using NBF.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerView : Entity
|
||||
{
|
||||
public Player Player { get; private set; }
|
||||
|
||||
public PlayerUnityComponent Unity { get; private set; }
|
||||
|
||||
#region 生命周期
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
Player = GetParent<Player>();
|
||||
var gameObject = PrefabsHelper.CreatePlayer(SceneSettings.Instance.Node);
|
||||
Unity = gameObject.GetComponent<PlayerUnityComponent>();
|
||||
Unity.Player = Player;
|
||||
CreatePlayerModel();
|
||||
if (Player.IsSelf)
|
||||
{
|
||||
CameraManager.Instance.SetFppLook(Unity);
|
||||
}
|
||||
|
||||
Unity.transform.localPosition = new Vector3(484, 1, 422);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public void LateUpdate()
|
||||
{
|
||||
Player.EyeAngle = GameUtils.GetVerticalAngle(Unity.transform, Unity.FppLook);
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 模型创建
|
||||
|
||||
private void CreatePlayerModel()
|
||||
{
|
||||
var modelObject = PrefabsHelper.CreatePlayer(Unity.Root, "Human_Male");
|
||||
modelObject.transform.localPosition = Vector3.zero;
|
||||
Unity.ModelAsset = modelObject.GetComponent<PlayerModelAsset>();
|
||||
Unity.ModelAsset.SetPlayer(Unity.FppLook);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 物品切换
|
||||
|
||||
public async FTask ChangeItem(PlayerItemChangeEvent playerStateChangeEvent)
|
||||
{
|
||||
var prevItem = playerStateChangeEvent.PrevItem;
|
||||
var currItem = playerStateChangeEvent.Item;
|
||||
if (Player.IsChangeItemIng) return;
|
||||
Player.IsChangeItemIng = true;
|
||||
if (currItem == null)
|
||||
{
|
||||
//收起物品
|
||||
await UnUseItem(prevItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 先收起旧的物品
|
||||
await UnUseItemConfirm(prevItem);
|
||||
var handItem = Player.HandItem;
|
||||
//拿起新物品
|
||||
var itemType = handItem.ConfigID.GetItemType();
|
||||
if (itemType == ItemType.Rod)
|
||||
{
|
||||
var itemView = handItem.GetOrAddComponent<PlayerItemView>();
|
||||
await itemView.InitShow(handItem);
|
||||
Unity.ModelAsset.PlayerAnimator.OnUseItem(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
var stateView = Player.GetComponent<PlayerStateView>();
|
||||
if (stateView != null && stateView.CurrentStateView is PlayerStageViewIdle playerStageViewIdle)
|
||||
{
|
||||
playerStageViewIdle.TakeLine();
|
||||
}
|
||||
|
||||
Player.IsChangeItemIng = false;
|
||||
}
|
||||
|
||||
#region 使用物品
|
||||
|
||||
public async FTask UnUseItem(PlayerItem item)
|
||||
{
|
||||
if (item == null) return;
|
||||
if (Player.IsChangeItemIng) return;
|
||||
Player.IsChangeItemIng = true;
|
||||
await UnUseItemConfirm(item);
|
||||
Player.IsChangeItemIng = false;
|
||||
}
|
||||
|
||||
private async FTask UnUseItemConfirm(PlayerItem item)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
Unity.ModelAsset.PlayerAnimator.OnUnUseItem();
|
||||
await FTask.Wait(Scene, 100);
|
||||
}
|
||||
|
||||
Player.ReleaseItem(item);
|
||||
await FTask.Wait(Scene, 450);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class PlayerViewAwakeSystem : AwakeSystem<PlayerView>
|
||||
{
|
||||
protected override void Awake(PlayerView self)
|
||||
{
|
||||
self.Awake();
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerViewDestroySystem : DestroySystem<PlayerView>
|
||||
{
|
||||
protected override void Destroy(PlayerView self)
|
||||
{
|
||||
self.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerViewUpdateSystem : UpdateSystem<PlayerView>
|
||||
{
|
||||
protected override void Update(PlayerView self)
|
||||
{
|
||||
self.Update();
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerViewLateUpdateSystem : LateUpdateSystem<PlayerView>
|
||||
{
|
||||
protected override void LateUpdate(PlayerView self)
|
||||
{
|
||||
self.LateUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 418da378516646cdb672fa05c2066432
|
||||
timeCreated: 1773037811
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98b05ca000114232a657f19095fdb49a
|
||||
timeCreated: 1773063071
|
||||
@@ -1,22 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public interface IPlayerThrowAnimation
|
||||
{
|
||||
Player Player { get; set; }
|
||||
bool IsPlaying { get; }
|
||||
void Play(ThrowAnimationRequest request);
|
||||
void Tick(float deltaTime);
|
||||
void Stop(bool snapToTarget);
|
||||
}
|
||||
|
||||
public struct ThrowAnimationRequest
|
||||
{
|
||||
public FLineLogicNode EndNode;
|
||||
public Vector3 ThrowOriginPosition;
|
||||
public Vector3 StartPosition;
|
||||
public Vector3 Forward;
|
||||
public float ChargedProgress;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51e9c4e20e460b34ca8ec4de6b7cab4b
|
||||
@@ -1,153 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class ParabolaPlayerThrowAnimation : IPlayerThrowAnimation
|
||||
{
|
||||
public Player Player { get; set; }
|
||||
|
||||
private const int TrajectorySampleCount = 24;
|
||||
|
||||
//
|
||||
// private readonly float _minThrowDistance;
|
||||
// private readonly float _maxThrowDistance;
|
||||
private readonly float _throwDuration;
|
||||
private readonly float _throwArcHeight;
|
||||
private readonly float _targetHeightOffset;
|
||||
private readonly AnimationCurve _throwHeightCurve;
|
||||
private readonly Vector3[] _lastTrajectoryPoints = new Vector3[TrajectorySampleCount + 1];
|
||||
|
||||
private bool _hasLastTrajectory;
|
||||
private float _chargedProgress;
|
||||
private float _castElapsedTime;
|
||||
private Vector3 _castStartPos;
|
||||
private Vector3 _castTargetPos;
|
||||
private FLineLogicNode _castingLure;
|
||||
|
||||
public bool IsPlaying => _castingLure != null;
|
||||
|
||||
public ParabolaPlayerThrowAnimation(
|
||||
float throwDuration = 0.45f,
|
||||
float throwArcHeight = 4f,
|
||||
float targetHeightOffset = 0f,
|
||||
AnimationCurve throwHeightCurve = null)
|
||||
{
|
||||
_throwDuration = throwDuration;
|
||||
_throwArcHeight = throwArcHeight;
|
||||
_targetHeightOffset = targetHeightOffset;
|
||||
_throwHeightCurve = throwHeightCurve ?? AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
|
||||
}
|
||||
|
||||
public void Play(ThrowAnimationRequest request)
|
||||
{
|
||||
if (request.EndNode == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Stop(snapToTarget: false);
|
||||
|
||||
_castingLure = request.EndNode;
|
||||
_chargedProgress = Mathf.Clamp01(request.ChargedProgress);
|
||||
_castElapsedTime = 0f;
|
||||
|
||||
var lureBody = request.EndNode.Rigidbody;
|
||||
_castStartPos = request.StartPosition;
|
||||
|
||||
Vector3 forward = GetHorizontalForward(request.Forward);
|
||||
|
||||
float distance = Mathf.Lerp(1, 8, _chargedProgress);
|
||||
_castTargetPos = request.ThrowOriginPosition + forward * distance;
|
||||
_castTargetPos.y = _castStartPos.y + _targetHeightOffset;
|
||||
|
||||
CacheTrajectoryPoints();
|
||||
|
||||
lureBody.isKinematic = true;
|
||||
lureBody.useGravity = false;
|
||||
lureBody.linearVelocity = Vector3.zero;
|
||||
lureBody.angularVelocity = Vector3.zero;
|
||||
lureBody.position = _castStartPos;
|
||||
}
|
||||
|
||||
public void Tick(float deltaTime)
|
||||
{
|
||||
UpdateCastAnimation(deltaTime);
|
||||
}
|
||||
|
||||
public void Stop(bool snapToTarget)
|
||||
{
|
||||
if (_castingLure == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var lureBody = _castingLure.Rigidbody;
|
||||
if (snapToTarget)
|
||||
{
|
||||
_castingLure.transform.position = _castTargetPos;
|
||||
lureBody.position = _castTargetPos;
|
||||
}
|
||||
|
||||
lureBody.linearVelocity = Vector3.zero;
|
||||
lureBody.angularVelocity = Vector3.zero;
|
||||
lureBody.useGravity = true;
|
||||
lureBody.isKinematic = false;
|
||||
|
||||
_castingLure = null;
|
||||
}
|
||||
|
||||
private void UpdateCastAnimation(float deltaTime)
|
||||
{
|
||||
if (_castingLure == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float duration = Mathf.Max(_throwDuration, 0.01f);
|
||||
_castElapsedTime += deltaTime;
|
||||
float progress = Mathf.Clamp01(_castElapsedTime / duration);
|
||||
|
||||
_castingLure.transform.position = EvaluateTrajectoryPosition(progress);
|
||||
|
||||
if (progress >= 1f)
|
||||
{
|
||||
Stop(snapToTarget: true);
|
||||
}
|
||||
}
|
||||
|
||||
private void CacheTrajectoryPoints()
|
||||
{
|
||||
for (int i = 0; i <= TrajectorySampleCount; i++)
|
||||
{
|
||||
float progress = i / (float)TrajectorySampleCount;
|
||||
_lastTrajectoryPoints[i] = EvaluateTrajectoryPosition(progress);
|
||||
}
|
||||
|
||||
_hasLastTrajectory = true;
|
||||
if (Player != null && Player.TrajectoryPoints != null)
|
||||
{
|
||||
Player.TrajectoryPoints.Clear();
|
||||
Player.TrajectoryPoints.AddRange(_lastTrajectoryPoints);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 GetHorizontalForward(Vector3 forward)
|
||||
{
|
||||
forward.y = 0f;
|
||||
if (forward.sqrMagnitude < 0.001f)
|
||||
{
|
||||
return Vector3.forward;
|
||||
}
|
||||
|
||||
return forward.normalized;
|
||||
}
|
||||
|
||||
private Vector3 EvaluateTrajectoryPosition(float progress)
|
||||
{
|
||||
Vector3 position = Vector3.Lerp(_castStartPos, _castTargetPos, progress);
|
||||
float arc = _throwHeightCurve.Evaluate(progress) * _throwArcHeight * _chargedProgress;
|
||||
position.y += arc;
|
||||
return position;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86121f3f07035144fadd467716b4b3a9
|
||||
@@ -1,213 +0,0 @@
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public enum PlayerState : uint
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 闲置等待中
|
||||
/// </summary>
|
||||
Idle = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 准备抛竿
|
||||
/// </summary>
|
||||
Prepare = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 抛竿中
|
||||
/// </summary>
|
||||
Throw = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 钓鱼中
|
||||
/// </summary>
|
||||
Fishing = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 溜鱼中
|
||||
/// </summary>
|
||||
Fight = 5
|
||||
}
|
||||
|
||||
public abstract class PlayerStageViewBase
|
||||
{
|
||||
public Player Player { get; private set; }
|
||||
public PlayerView PlayerView { get; private set; }
|
||||
protected float EnterTime { get; set; }
|
||||
|
||||
protected PlayerState PreviousState { get; private set; }
|
||||
protected StateEnterParams Params;
|
||||
|
||||
public void Init(Player player)
|
||||
{
|
||||
Player = player;
|
||||
PlayerView = player.GetComponent<PlayerView>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查状态超时
|
||||
/// </summary>
|
||||
public void CheckStateTimeout(float time)
|
||||
{
|
||||
if (Time.time - EnterTime >= time)
|
||||
{
|
||||
Player.ChangeState(PlayerState.Idle);
|
||||
}
|
||||
}
|
||||
|
||||
public void Enter(StateEnterParams par = null, PlayerState prevState = PlayerState.None)
|
||||
{
|
||||
Log.Info($"进入状态={GetType()}");
|
||||
Params = par;
|
||||
PreviousState = prevState;
|
||||
EnterTime = Time.time;
|
||||
OnEnter();
|
||||
}
|
||||
|
||||
protected virtual void OnEnter()
|
||||
{
|
||||
}
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
OnExit();
|
||||
}
|
||||
|
||||
protected virtual void OnExit()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
OnUpdate();
|
||||
}
|
||||
|
||||
protected virtual void OnUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
#region 鱼线操作
|
||||
|
||||
public void TakeLine()
|
||||
{
|
||||
if (Player == null) return;
|
||||
var view = Player.GetComponent<PlayerView>();
|
||||
if (view != null)
|
||||
{
|
||||
var handItemView = Player.HandItem.GetComponent<PlayerItemView>();
|
||||
if (handItemView != null && handItemView.Rod != null)
|
||||
{
|
||||
var endNode = handItemView.Rod.Line.EndNode;
|
||||
var pinch = endNode.GetComponent<JointPinchController>();
|
||||
if (pinch != null)
|
||||
{
|
||||
pinch.StartPinch(view.Unity.ModelAsset.Pinch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UnTakeLine()
|
||||
{
|
||||
if (Player == null) return;
|
||||
var view = Player.GetComponent<PlayerView>();
|
||||
if (view != null)
|
||||
{
|
||||
var handItemView = Player.HandItem.GetComponent<PlayerItemView>();
|
||||
if (handItemView != null && handItemView.Rod != null)
|
||||
{
|
||||
var endNode = handItemView.Rod.Line.EndNode;
|
||||
var pinch = endNode.GetComponent<JointPinchController>();
|
||||
if (pinch != null)
|
||||
{
|
||||
pinch.ReleasePinch();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 鱼竿操作
|
||||
|
||||
protected void RodUpDown()
|
||||
{
|
||||
PlayerState ret = PlayerState.None;
|
||||
var isUpRod = false;
|
||||
var isSubLine = false;
|
||||
|
||||
if (InputManager.IsOp1)
|
||||
{
|
||||
if (!Player.IsLureRod)
|
||||
{
|
||||
//抬杆
|
||||
isUpRod = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//收线
|
||||
isSubLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (InputManager.IsOp2)
|
||||
{
|
||||
if (Player.IsLureRod)
|
||||
{
|
||||
//抬杆
|
||||
isUpRod = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isUpRod || PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp > 0)
|
||||
{
|
||||
var upForce = 1;
|
||||
var addNum = upForce * Time.deltaTime;
|
||||
if (!isUpRod)
|
||||
{
|
||||
addNum *= -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
addNum *= 0.5f;
|
||||
}
|
||||
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp += addNum;
|
||||
Debug.Log($"addNum={addNum} ishingFinal={PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp}");
|
||||
if (PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp >= 1)
|
||||
{
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp = 1;
|
||||
}
|
||||
else if (PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp < 0)
|
||||
{
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public FRod GetRod()
|
||||
{
|
||||
var view = Player.GetComponent<PlayerView>();
|
||||
if (view != null)
|
||||
{
|
||||
var handItemView = Player.HandItem.GetComponent<PlayerItemView>();
|
||||
if (handItemView != null && handItemView.Rod != null)
|
||||
{
|
||||
return handItemView.Rod;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cce89f03f80b4fb8a0e36e66e9ffb3a9
|
||||
timeCreated: 1773063081
|
||||
@@ -1,29 +0,0 @@
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerStageViewFight : PlayerStageViewBase
|
||||
{
|
||||
protected override void OnEnter()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnExit()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
PlayerState ret = PlayerState.None;
|
||||
RodUpDown();
|
||||
|
||||
if (PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp >= 0.8f)
|
||||
{
|
||||
// ret = CheckTackFish();
|
||||
}
|
||||
|
||||
if (ret != PlayerState.None)
|
||||
{
|
||||
Player.ChangeState(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9445a6593604dc19dea2bb8bb0819bc
|
||||
timeCreated: 1773064542
|
||||
@@ -1,109 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerStageViewFishing : PlayerStageViewBase
|
||||
{
|
||||
protected override void OnEnter()
|
||||
{
|
||||
Debug.LogError("enter PlayerStateFishing");
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.BaitThrown = true;
|
||||
}
|
||||
|
||||
protected override void OnExit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
PlayerState ret = PlayerState.None;
|
||||
RodUpDown();
|
||||
|
||||
if (PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp >= 0.8f)
|
||||
{
|
||||
ret = CheckTackFish();
|
||||
}
|
||||
|
||||
if (ret != PlayerState.None)
|
||||
{
|
||||
Player.ChangeState(ret);
|
||||
}
|
||||
|
||||
// var isUpRod = false;
|
||||
// var isSubLine = false;
|
||||
//
|
||||
// if (InputManager.IsOp1)
|
||||
// {
|
||||
// if (!Player.IsLureRod)
|
||||
// {
|
||||
// //抬杆
|
||||
// isUpRod = true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //收线
|
||||
// isSubLine = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (InputManager.IsOp2)
|
||||
// {
|
||||
// if (Player.IsLureRod)
|
||||
// {
|
||||
// //抬杆
|
||||
// isUpRod = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (isUpRod || PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp > 0)
|
||||
// {
|
||||
// var upForce = 1;
|
||||
// var addNum = upForce * Time.deltaTime;
|
||||
// if (!isUpRod)
|
||||
// {
|
||||
// addNum *= -1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// addNum *= 0.5f;
|
||||
// }
|
||||
//
|
||||
// PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp += addNum;
|
||||
// Debug.Log($"addNum={addNum} ishingFinal={PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp}");
|
||||
// if (PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp >= 1)
|
||||
// {
|
||||
// PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp = 1;
|
||||
// }
|
||||
// else if (PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp < 0)
|
||||
// {
|
||||
// PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
// }
|
||||
//
|
||||
// if (PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp >= 0.8f)
|
||||
// {
|
||||
// ret = CheckTackFish();
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
// }
|
||||
//
|
||||
// if (ret != PlayerState.None)
|
||||
// {
|
||||
// Player.ChangeState(ret);
|
||||
// }
|
||||
}
|
||||
|
||||
#region 检查上鱼或者返回待机
|
||||
|
||||
private PlayerState CheckTackFish()
|
||||
{
|
||||
// return PlayerState.Idle;
|
||||
return PlayerState.Fight;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84665b6bc7c84642b365db024c7759fd
|
||||
timeCreated: 1773064529
|
||||
@@ -1,28 +0,0 @@
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerStageViewIdle : PlayerStageViewBase
|
||||
{
|
||||
protected override void OnEnter()
|
||||
{
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.BaitThrown = false;
|
||||
InputManager.OnOp1Action += OnOp1Action;
|
||||
TakeLine();
|
||||
}
|
||||
|
||||
private void OnOp1Action(bool performed)
|
||||
{
|
||||
if (Player.HandItem == null) return;
|
||||
if (performed)
|
||||
{
|
||||
Player.ChangeState(PlayerState.Prepare);
|
||||
// _nextState = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnExit()
|
||||
{
|
||||
InputManager.OnOp1Action -= OnOp1Action;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fca81636d7246e7a5f84684a8563ca3
|
||||
timeCreated: 1773063824
|
||||
@@ -1,75 +0,0 @@
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerStageViewPrepare : PlayerStageViewBase
|
||||
{
|
||||
public enum Phase
|
||||
{
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// 蓄力
|
||||
/// </summary>
|
||||
Charged,
|
||||
|
||||
/// <summary>
|
||||
/// 确认蓄力结果
|
||||
/// </summary>
|
||||
Confirm,
|
||||
}
|
||||
|
||||
public Phase Stage = Phase.Charged;
|
||||
public float ChargedProgress;
|
||||
|
||||
protected override void OnEnter()
|
||||
{
|
||||
Log.Info("enter PlayerStatePrepare");
|
||||
ChargedProgress = 0;
|
||||
Stage = Phase.Charged;
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.PrepareThrow = true;
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (Stage == Phase.Charged)
|
||||
{
|
||||
ThrowPowerCharged();
|
||||
}
|
||||
else if (Stage == Phase.Confirm)
|
||||
{
|
||||
//确认蓄力结果,
|
||||
Debug.Log($"确认蓄力结果,ChargedProgress={ChargedProgress}");
|
||||
var par = new StateEnterParams();
|
||||
par.SetFloat(StateParamsConst.ChargedProgress, ChargedProgress);
|
||||
Player.ChangeState(PlayerState.Throw, par);
|
||||
Stage = Phase.None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region 蓄力中
|
||||
|
||||
private void ThrowPowerCharged()
|
||||
{
|
||||
if (ChargedProgress < 1)
|
||||
{
|
||||
ChargedProgress += Time.deltaTime * 0.5f;
|
||||
Debug.Log($"ChargedProgress={ChargedProgress}");
|
||||
}
|
||||
else if (ChargedProgress > 1)
|
||||
{
|
||||
ChargedProgress = 1;
|
||||
}
|
||||
|
||||
if (!InputManager.IsOp1)
|
||||
{
|
||||
Stage = Phase.Confirm;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77cce716a7f94e0083789eb2953d5f79
|
||||
timeCreated: 1773064499
|
||||
@@ -1,111 +0,0 @@
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerStageViewThrow : PlayerStageViewBase
|
||||
{
|
||||
private bool _nextState = false;
|
||||
private bool _throwAnimEnded = false;
|
||||
private IPlayerThrowAnimation _throwAnimation;
|
||||
|
||||
public float ChargedProgress;
|
||||
|
||||
protected override void OnEnter()
|
||||
{
|
||||
Log.Info("enter PlayerStateThrow");
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.StartThrow = true;
|
||||
|
||||
ChargedProgress = 0;
|
||||
if (Params != null)
|
||||
{
|
||||
ChargedProgress = Params.GetFloat(StateParamsConst.ChargedProgress);
|
||||
}
|
||||
|
||||
Debug.Log($"PlayerThrow ChargedProgress={ChargedProgress}");
|
||||
_nextState = false;
|
||||
_throwAnimEnded = false;
|
||||
_throwAnimation = null;
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
CheckStateTimeout(10);
|
||||
_throwAnimation?.Tick(Time.deltaTime);
|
||||
|
||||
if (_throwAnimEnded && (_throwAnimation == null || !_throwAnimation.IsPlaying))
|
||||
{
|
||||
_nextState = true;
|
||||
}
|
||||
|
||||
if (_nextState)
|
||||
{
|
||||
_nextState = false;
|
||||
Player.ChangeState(PlayerState.Fishing);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnExit()
|
||||
{
|
||||
_throwAnimation?.Stop(snapToTarget: false);
|
||||
_throwAnimation = null;
|
||||
}
|
||||
|
||||
#region 动画回调
|
||||
|
||||
public void OnRodThrowStart()
|
||||
{
|
||||
Debug.LogError("OnRodThrowStart");
|
||||
UnTakeLine();
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.PrepareThrow = false;
|
||||
PlayerView.Unity.ModelAsset.PlayerAnimator.StartThrow = false;
|
||||
|
||||
var rod = GetRod();
|
||||
if (rod == null || rod.Line == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_throwAnimation = CreateThrowAnimation(rod);
|
||||
_throwAnimation.Player = Player;
|
||||
_throwAnimation?.Play(new ThrowAnimationRequest
|
||||
{
|
||||
EndNode = rod.Line.EndNode,
|
||||
ThrowOriginPosition = PlayerView.Unity.transform.position,
|
||||
StartPosition = rod.Line.EndNode.Rigidbody.position,
|
||||
Forward = PlayerView.Unity.transform.forward,
|
||||
ChargedProgress = ChargedProgress
|
||||
});
|
||||
}
|
||||
|
||||
public void OnRodThrownEnd()
|
||||
{
|
||||
Debug.LogError("OnRodThrownEnd");
|
||||
_throwAnimEnded = true;
|
||||
if (_throwAnimation == null || !_throwAnimation.IsPlaying)
|
||||
{
|
||||
_nextState = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private IPlayerThrowAnimation CreateThrowAnimation(FRod rod)
|
||||
{
|
||||
if (rod == null || rod.Line == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (rod.Line.LineType)
|
||||
{
|
||||
case LineType.Spinning:
|
||||
case LineType.SpinningFloat:
|
||||
case LineType.Hand:
|
||||
case LineType.HandDouble:
|
||||
default:
|
||||
return new ParabolaPlayerThrowAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 240bbc6c969a4d2e9759ac1df5e6ccf2
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 139e43e2a118492c974b67decf15056d
|
||||
timeCreated: 1766477309
|
||||
@@ -1,14 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FBait : FGearBase
|
||||
{
|
||||
protected override void OnInit()
|
||||
{
|
||||
var baitConnector = Rod.Hook.hookAsset.baitConnector;
|
||||
transform.position = baitConnector.position;
|
||||
transform.SetParent(baitConnector);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed7126c6f37c427e88ba321c63aeac2f
|
||||
timeCreated: 1766582532
|
||||
@@ -1,17 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FBobber : FGearBase
|
||||
{
|
||||
protected override void OnInit()
|
||||
{
|
||||
// transform.position = Rod.lineHandler.LineConnector_1.transform.position;
|
||||
var endNode = Rod.Line.GetNode(FLineLogicNodeType.Bobber);
|
||||
SetParent(endNode.transform);
|
||||
transform.localPosition = Vector3.zero;
|
||||
// var buoyancy = GetComponentInParent<CapsuleBuoyancyStable>();
|
||||
// buoyancy.InitBobber();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89060cfcd521410caf2f00ae7ecfa135
|
||||
timeCreated: 1766477995
|
||||
@@ -1,9 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FFish : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d76aeec1876a4df2a93e8e8dcaee30fa
|
||||
timeCreated: 1766586324
|
||||
@@ -1,35 +0,0 @@
|
||||
using Fantasy;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public abstract class FGearBase : MonoBehaviour
|
||||
{
|
||||
public FRod Rod { get; protected set; }
|
||||
|
||||
public int ConfigId;
|
||||
|
||||
|
||||
public virtual void Init(FRod rod)
|
||||
{
|
||||
Rod = rod;
|
||||
OnInit();
|
||||
}
|
||||
|
||||
public void SetItemConfigId(int id)
|
||||
{
|
||||
ConfigId = id;
|
||||
}
|
||||
|
||||
|
||||
protected void SetParent(Transform parent)
|
||||
{
|
||||
transform.SetParent(parent);
|
||||
transform.localPosition = Vector3.zero;
|
||||
transform.localEulerAngles = Vector3.zero;
|
||||
transform.localScale = Vector3.one;
|
||||
}
|
||||
|
||||
protected abstract void OnInit();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 708753789f5b41f48b9b18197f54a9df
|
||||
timeCreated: 1766582740
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user