首次提交
This commit is contained in:
3
Assets/Scripts/Fishing/Animator.meta
Normal file
3
Assets/Scripts/Fishing/Animator.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcae353a013f4bd8bd4818abbcbe6959
|
||||
timeCreated: 1766743259
|
||||
55
Assets/Scripts/Fishing/Animator/ReelAnimator.cs
Normal file
55
Assets/Scripts/Fishing/Animator/ReelAnimator.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Animator/ReelAnimator.cs.meta
Normal file
3
Assets/Scripts/Fishing/Animator/ReelAnimator.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dad5b24d68464595b58a0d8fea28a10b
|
||||
timeCreated: 1766743262
|
||||
38
Assets/Scripts/Fishing/BobberController.cs
Normal file
38
Assets/Scripts/Fishing/BobberController.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/BobberController.cs.meta
Normal file
3
Assets/Scripts/Fishing/BobberController.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e9411b5edc6466a8014c59e3821bbaa
|
||||
timeCreated: 1768918059
|
||||
63
Assets/Scripts/Fishing/Fishing.cs
Normal file
63
Assets/Scripts/Fishing/Fishing.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using NBF.Fishing2;
|
||||
using RootMotion.FinalIK;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class Fishing
|
||||
{
|
||||
public FPlayer Player { get; private set; }
|
||||
private static Fishing _instance;
|
||||
|
||||
public static Fishing Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
_instance ??= new Fishing();
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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}");
|
||||
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)
|
||||
{
|
||||
var sceneName = "Map1";
|
||||
//加载场景==
|
||||
await SceneHelper.LoadScene(sceneName);
|
||||
CreateUnit();
|
||||
}
|
||||
|
||||
|
||||
private void CreateUnit()
|
||||
{
|
||||
var gameObject = PrefabsHelper.CreatePlayer(SceneSettings.Instance.Node);
|
||||
Player = gameObject.GetComponent<FPlayer>();
|
||||
CameraManager.Instance.Mode = CameraShowMode.FPP;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Fishing.cs.meta
Normal file
3
Assets/Scripts/Fishing/Fishing.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0afcee9eb5f848e08b2fae2cc673b6d8
|
||||
timeCreated: 1766414593
|
||||
7
Assets/Scripts/Fishing/FishingMap.cs
Normal file
7
Assets/Scripts/Fishing/FishingMap.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace NBF
|
||||
{
|
||||
public class FishingMap
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/FishingMap.cs.meta
Normal file
3
Assets/Scripts/Fishing/FishingMap.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c361da1bcda647eb96fa27af894d2a7a
|
||||
timeCreated: 1766417823
|
||||
33
Assets/Scripts/Fishing/FixedLine.cs
Normal file
33
Assets/Scripts/Fishing/FixedLine.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/FixedLine.cs.meta
Normal file
3
Assets/Scripts/Fishing/FixedLine.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec22ad0246c24123a6511e60e753ee38
|
||||
timeCreated: 1766586205
|
||||
3
Assets/Scripts/Fishing/Helper.meta
Normal file
3
Assets/Scripts/Fishing/Helper.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4177c0c4cf94787b06ec92973ba4722
|
||||
timeCreated: 1766412118
|
||||
67
Assets/Scripts/Fishing/Helper/LoginHelper.cs
Normal file
67
Assets/Scripts/Fishing/Helper/LoginHelper.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Helper/LoginHelper.cs.meta
Normal file
3
Assets/Scripts/Fishing/Helper/LoginHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 031ed023449844cdb9d6c4eb5d7fee90
|
||||
timeCreated: 1755698636
|
||||
115
Assets/Scripts/Fishing/Helper/MapHelper.cs
Normal file
115
Assets/Scripts/Fishing/Helper/MapHelper.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
// 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
|
||||
// }
|
||||
// }
|
||||
3
Assets/Scripts/Fishing/Helper/MapHelper.cs.meta
Normal file
3
Assets/Scripts/Fishing/Helper/MapHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfc04c7d83084b7784cb7cf69dde1be6
|
||||
timeCreated: 1756132207
|
||||
48
Assets/Scripts/Fishing/Helper/PrefabsHelper.cs
Normal file
48
Assets/Scripts/Fishing/Helper/PrefabsHelper.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Helper/PrefabsHelper.cs.meta
Normal file
3
Assets/Scripts/Fishing/Helper/PrefabsHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18ffcf16981040b2a88990281adcb4ac
|
||||
timeCreated: 1756451102
|
||||
39
Assets/Scripts/Fishing/Helper/SceneHelper.cs
Normal file
39
Assets/Scripts/Fishing/Helper/SceneHelper.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Helper/SceneHelper.cs.meta
Normal file
3
Assets/Scripts/Fishing/Helper/SceneHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4a2e9c0ac6d4faabbec4bccdb7a2917
|
||||
timeCreated: 1756367987
|
||||
41
Assets/Scripts/Fishing/LureController.cs
Normal file
41
Assets/Scripts/Fishing/LureController.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class LureController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Rigidbody rBody;
|
||||
[SerializeField] private ConfigurableJoint joint;
|
||||
public Rigidbody RBody => rBody;
|
||||
|
||||
public ConfigurableJoint Joint => joint;
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/LureController.cs.meta
Normal file
3
Assets/Scripts/Fishing/LureController.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed5bbbc032ec4ca1bb56991d9141e311
|
||||
timeCreated: 1768918224
|
||||
3
Assets/Scripts/Fishing/Player.meta
Normal file
3
Assets/Scripts/Fishing/Player.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f89752d44de4cf798a163bf6a554e8e
|
||||
timeCreated: 1766419447
|
||||
93
Assets/Scripts/Fishing/Player/FPlayer.Input.cs
Normal file
93
Assets/Scripts/Fishing/Player/FPlayer.Input.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using NBC;
|
||||
using NBF.Utils;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public partial class FPlayer
|
||||
{
|
||||
#region Input
|
||||
|
||||
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)
|
||||
{
|
||||
Data.Run = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerCanceled(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Data.Run = false;
|
||||
}
|
||||
else if (action == InputDef.Player.ToBag)
|
||||
{
|
||||
//取消手持物品
|
||||
Log.Info($"取消手持物品");
|
||||
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)
|
||||
{
|
||||
Game.Instance.StartCoroutine(UseItem(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValueCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
var actionName = context.action.name;
|
||||
if (actionName == InputDef.Player.Move)
|
||||
{
|
||||
// var v2 = context.ReadValue<Vector2>();
|
||||
Data.MoveInput = Vector2.zero;
|
||||
// SendMoveMessage(v2, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValuePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
// var mapUnit = Parent as MapUnit;
|
||||
// Log.Info($"OnPlayerValuePerformed IsSelf={mapUnit.IsSelf()} id={mapUnit.Id}");
|
||||
var actionName = context.action.name;
|
||||
if (actionName == InputDef.Player.Move)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
Data.MoveInput = v2;
|
||||
// SendMoveMessage(v2, false);
|
||||
}
|
||||
else if (actionName == InputDef.Player.Look)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
// UpdatePlayerRotation(v2);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Player/FPlayer.Input.cs.meta
Normal file
3
Assets/Scripts/Fishing/Player/FPlayer.Input.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea2c2e2d4b4344f0bc9d58ba0aeec6fd
|
||||
timeCreated: 1766505279
|
||||
146
Assets/Scripts/Fishing/Player/FPlayer.Move.cs
Normal file
146
Assets/Scripts/Fishing/Player/FPlayer.Move.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public partial class FPlayer
|
||||
{
|
||||
#region Move
|
||||
|
||||
private Quaternion lastRotation;
|
||||
|
||||
private void UpdateMove()
|
||||
{
|
||||
UpdateGrounded();
|
||||
UpdateWater();
|
||||
ProcessMoveStates();
|
||||
UpdateLookInput();
|
||||
}
|
||||
|
||||
private void UpdateGrounded()
|
||||
{
|
||||
Data.IsGrounded = FirstPerson.IsGrounded();
|
||||
Data.Speed = FirstPerson.velocity.magnitude;
|
||||
|
||||
Quaternion rotation = 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);
|
||||
|
||||
|
||||
Data.RotationSpeed = turnValue;
|
||||
|
||||
lastRotation = rotation;
|
||||
}
|
||||
|
||||
private void UpdateWater()
|
||||
{
|
||||
// SceneSettings.Instance.Water.w
|
||||
}
|
||||
|
||||
private void ProcessMoveStates()
|
||||
{
|
||||
// if (CameraView.Value == CameraViewType.TPP)
|
||||
// {
|
||||
// float num = (IsRunPressed.Value ? MovementSpeed.Value : (MovementSpeed.Value * 0.5f));
|
||||
// num = (IsFlyModeEnabled ? (num * (float)FlySpeed) : num);
|
||||
// Vector3 zero = Vector3.zero;
|
||||
// zero += Vector3.right * MovementDirection.Value.x;
|
||||
// zero += Vector3.forward * MovementDirection.Value.y;
|
||||
// zero = zero.relativeTo(_CameraTPPTarget, _Character.GetUpVector());
|
||||
// _Character.RotateTowards(zero, Time.deltaTime * _RotateTPPSpeed);
|
||||
// float value = Vector3.Dot(_Character.GetForwardVector(), zero);
|
||||
// Vector3 vector = _Character.GetForwardVector() * Mathf.Clamp01(value) * num;
|
||||
// if (checkWaterBound)
|
||||
// {
|
||||
// SetMovementDirectionWithRaycastCheck(vector);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _Character.SetMovementDirection(vector);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
{
|
||||
var num2 = Data.Run ? 7 : 5;
|
||||
//(IsRunPressed.Value ? MovementSpeed.Value : (MovementSpeed.Value * 0.5f));
|
||||
// num2 = (IsFlyModeEnabled ? (num2 * (float)FlySpeed) : num2);
|
||||
Vector3 vector2 = FirstPerson.GetRightVector() * Data.MoveInput.x * num2;
|
||||
vector2 += FirstPerson.GetForwardVector() * Data.MoveInput.y * num2;
|
||||
// if (checkWaterBound)
|
||||
// {
|
||||
// SetMovementDirectionWithRaycastCheck(vector2);
|
||||
// }
|
||||
// else
|
||||
{
|
||||
FirstPerson.SetMovementDirection(vector2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Look
|
||||
|
||||
public float MouseSensitivity = 0.1f;
|
||||
[Space(15f)] public bool invertLook = true;
|
||||
|
||||
public float minPitch = -60f;
|
||||
|
||||
public float maxPitch = 60f;
|
||||
|
||||
private void UpdateLookInput()
|
||||
{
|
||||
// TPPLookTarget.position = base.transform.position;
|
||||
// if (CameraView.Value == CameraViewType.TPP)
|
||||
// {
|
||||
// lookXRot -= MouseInput.Value.y;
|
||||
// lookXRot = Mathf.Clamp(lookXRot, -25f, 55f);
|
||||
// lookYRot += MouseInput.Value.x;
|
||||
// lookYRot = Mathf.Repeat(lookYRot, 360f);
|
||||
// TPPLookTarget.localEulerAngles = new Vector3(lookXRot, lookYRot, 0f);
|
||||
// }
|
||||
// else if (CameraView.Value == CameraViewType.FPP)
|
||||
{
|
||||
// if (_IsInVehicle && PlayerState.Value == State.vehicle)
|
||||
// {
|
||||
// lookXRot -= MouseInput.Value.y;
|
||||
// lookXRot = Mathf.Clamp(lookXRot, VehicleLookXMinMax.x, VehicleLookXMinMax.y);
|
||||
// lookYRot += MouseInput.Value.x;
|
||||
// lookYRot = Mathf.Clamp(lookYRot, VehicleLookYMinMax.x, VehicleLookYMinMax.y);
|
||||
// VehicleLookTargetParent.localEulerAngles = new Vector3(lookXRot, lookYRot, 0f);
|
||||
// _character.CameraPitch = 0f;
|
||||
// }
|
||||
// else
|
||||
{
|
||||
Vector2 value = InputManager.GetLookInput();
|
||||
FirstPerson.AddControlYawInput(value.x * (float)MouseSensitivity);
|
||||
FirstPerson.AddControlPitchInput((invertLook ? (0f - value.y) : value.y) * (float)MouseSensitivity,
|
||||
minPitch, maxPitch);
|
||||
// lookXRot = base.transform.eulerAngles.x;
|
||||
// lookYRot = base.transform.eulerAngles.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Player/FPlayer.Move.cs.meta
Normal file
3
Assets/Scripts/Fishing/Player/FPlayer.Move.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae72860c045147af8022a3cbb30481ab
|
||||
timeCreated: 1766471468
|
||||
165
Assets/Scripts/Fishing/Player/FPlayer.cs
Normal file
165
Assets/Scripts/Fishing/Player/FPlayer.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using ECM2;
|
||||
using ECM2.Examples.FirstPerson;
|
||||
using Fantasy;
|
||||
using NBC;
|
||||
using NBF.Fishing2;
|
||||
using NBF.Utils;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public partial class FPlayer : MonoService<FPlayer>
|
||||
{
|
||||
public Transform Root;
|
||||
public Transform Eye;
|
||||
public Transform FppLook;
|
||||
public Transform IK;
|
||||
public PlayerModelAsset ModelAsset;
|
||||
public CharacterMovement Character;
|
||||
public FirstPersonCharacter FirstPerson;
|
||||
public GameObject ModelGameObject { get; set; }
|
||||
|
||||
|
||||
public FPlayerData Data { get; private set; }
|
||||
|
||||
public readonly List<FRod> Tackles = new List<FRod>();
|
||||
public FRod Rod { get; private set; }
|
||||
public Fsm<FPlayer> Fsm { get; private set; }
|
||||
|
||||
public event Action<FHandItem> OnFishingSetEquiped;
|
||||
public event Action OnFishingSetUnequip;
|
||||
|
||||
protected override void OnAwake()
|
||||
{
|
||||
Character = gameObject.GetComponent<CharacterMovement>();
|
||||
FirstPerson = gameObject.GetComponent<FirstPersonCharacter>();
|
||||
Data = FPlayerData.Instance;
|
||||
transform.localPosition = new Vector3(484, 1, 422);
|
||||
// Data.NeedChangeRightArmAngle = true;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
InitFsm();
|
||||
AddInputEvent();
|
||||
CreatePlayerModel();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
UpdateMove();
|
||||
Fsm?.Update();
|
||||
|
||||
Data.EyeAngle = GameUtils.GetVerticalAngle(transform, FppLook);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
RemoveInputEvent();
|
||||
}
|
||||
|
||||
#region 状态机
|
||||
|
||||
private void InitFsm()
|
||||
{
|
||||
Fsm = new Fsm<FPlayer>("Player", this, true);
|
||||
Fsm.RegisterState<PlayerStateIdle>();
|
||||
Fsm.RegisterState<PlayerStateThrow>();
|
||||
Fsm.RegisterState<PlayerStateFishing>();
|
||||
Fsm.RegisterState<PlayerStateFight>();
|
||||
Fsm.RegisterState<PlayerStatePrepare>();
|
||||
Fsm.Start<PlayerStateIdle>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 角色模型
|
||||
|
||||
private void CreatePlayerModel()
|
||||
{
|
||||
var modelObject = PrefabsHelper.CreatePlayer(Root, "Human_Male");
|
||||
modelObject.transform.localPosition = Vector3.zero;
|
||||
ModelGameObject = modelObject;
|
||||
ModelAsset = modelObject.GetComponent<PlayerModelAsset>();
|
||||
ModelAsset.SetPlayer(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 使用物品
|
||||
|
||||
public IEnumerator UseItem(ItemInfo item)
|
||||
{
|
||||
if (Data.ChangeItem) yield break;
|
||||
Data.ChangeItem = true;
|
||||
var itemType = item?.ConfigId.GetItemType();
|
||||
if (itemType == ItemType.Rod)
|
||||
{
|
||||
//判断旧的是否要收回
|
||||
yield return UnUseItemConfirm();
|
||||
|
||||
Data.IsLureRod = true;
|
||||
var rodType = (ItemSubType)item.Config.Type;
|
||||
if (rodType == ItemSubType.RodTele)
|
||||
{
|
||||
Data.IsLureRod = false;
|
||||
}
|
||||
|
||||
Rod =
|
||||
item.Config.InstantiateAndComponent<FRod>(SceneSettings.Instance.GearNode, Vector3.zero,
|
||||
Quaternion.identity);
|
||||
yield return Rod.InitRod(this, item);
|
||||
Tackles.Add(Rod);
|
||||
OnFishingSetEquiped?.Invoke(Rod);
|
||||
}
|
||||
|
||||
Data.ChangeItem = false;
|
||||
}
|
||||
|
||||
public IEnumerator UnUseItem()
|
||||
{
|
||||
if (Data.ChangeItem) yield break;
|
||||
Data.ChangeItem = true;
|
||||
yield return UnUseItemConfirm();
|
||||
Data.ChangeItem = false;
|
||||
}
|
||||
|
||||
private IEnumerator UnUseItemConfirm()
|
||||
{
|
||||
if (Rod != null)
|
||||
{
|
||||
OnFishingSetUnequip?.Invoke();
|
||||
yield return Rod.Destroy();
|
||||
yield return new WaitForSeconds(0.35f);
|
||||
Destroy(Rod.gameObject);
|
||||
Tackles.Remove(Rod);
|
||||
Rod = null;
|
||||
yield return new WaitForSeconds(0.15f);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 线断了
|
||||
/// </summary>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="loseBaitChance"></param>
|
||||
public void LineBreak(string msg, float loseBaitChance)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Player/FPlayer.cs.meta
Normal file
3
Assets/Scripts/Fishing/Player/FPlayer.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 625346c970c542bab9f3a36f78720a77
|
||||
timeCreated: 1766419452
|
||||
116
Assets/Scripts/Fishing/Player/FPlayerData.cs
Normal file
116
Assets/Scripts/Fishing/Player/FPlayerData.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
// [Serializable]
|
||||
// public enum PlayerState
|
||||
// {
|
||||
// idle = 0,
|
||||
// move = 1,
|
||||
// prepare = 2,
|
||||
// casting = 3,
|
||||
// fishing = 4,
|
||||
// baitFlies = 5,
|
||||
// fight = 6,
|
||||
// fishView = 7,
|
||||
// collectFish = 8,
|
||||
// throwFish = 9,
|
||||
// vehicle = 10,
|
||||
// swiming = 11,
|
||||
// flyModeDebug = 12,
|
||||
// vehicleFishing = 13,
|
||||
// preciseCastIdle = 14,
|
||||
// preciseCastThrow = 15
|
||||
// }
|
||||
|
||||
[Serializable]
|
||||
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 class FPlayerData : MonoService<FPlayerData>
|
||||
{
|
||||
private PlayerState _previousPlayerState = PlayerState.Idle;
|
||||
private PlayerState _playerState;
|
||||
|
||||
public bool ChangeItem;
|
||||
public bool Run;
|
||||
public bool IsGrounded;
|
||||
public float Speed;
|
||||
public float RotationSpeed;
|
||||
public float ReelSpeed;
|
||||
public float LineTension;
|
||||
|
||||
/// <summary>
|
||||
/// 是否路亚竿
|
||||
/// </summary>
|
||||
public bool IsLureRod;
|
||||
|
||||
public Vector2 MoveInput;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float EyeAngle;
|
||||
|
||||
|
||||
public PlayerState PreviousState => _previousPlayerState;
|
||||
|
||||
public PlayerState State
|
||||
{
|
||||
get => _playerState;
|
||||
set
|
||||
{
|
||||
_previousPlayerState = _playerState;
|
||||
_playerState = value;
|
||||
NextState = value;
|
||||
OnStateChange?.Invoke(_playerState);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] private PlayerState NextState;
|
||||
|
||||
public event Action<PlayerState> OnStateChange;
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
NextState = State;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (NextState != State)
|
||||
{
|
||||
State = NextState;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Player/FPlayerData.cs.meta
Normal file
3
Assets/Scripts/Fishing/Player/FPlayerData.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53629a9cec2b4caf9a739c21f7abdf3c
|
||||
timeCreated: 1766471002
|
||||
306
Assets/Scripts/Fishing/Player/PlayerAnimator.cs
Normal file
306
Assets/Scripts/Fishing/Player/PlayerAnimator.cs
Normal file
@@ -0,0 +1,306 @@
|
||||
using System;
|
||||
using KINEMATION.MagicBlend.Runtime;
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerAnimator : MonoBehaviour
|
||||
{
|
||||
public Animator _Animator;
|
||||
public FPlayer Player { get; private set; }
|
||||
|
||||
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
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Player = GetComponentInParent<FPlayer>();
|
||||
_magicBlending = GetComponent<MagicBlending>();
|
||||
_Animator = GetComponent<Animator>();
|
||||
_Animator.keepAnimatorStateOnDisable = true;
|
||||
_IK = GetComponent<PlayerIK>();
|
||||
_isInit = true;
|
||||
Player.OnFishingSetEquiped += OnFishingSetEquiped_OnRaised;
|
||||
Player.OnFishingSetUnequip += OnFishingSetUnequip;
|
||||
Player.Data.OnStateChange += PlayerFSMState_OnValueChanged;
|
||||
}
|
||||
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Player.OnFishingSetEquiped -= OnFishingSetEquiped_OnRaised;
|
||||
Player.OnFishingSetUnequip -= OnFishingSetUnequip;
|
||||
Player.Data.OnStateChange += PlayerFSMState_OnValueChanged;
|
||||
}
|
||||
|
||||
|
||||
private void OnFishingSetUnequip()
|
||||
{
|
||||
_isRodLayerEnabled = false;
|
||||
// _IK.SetBipedLeftHandIK(enabled: false, null);
|
||||
}
|
||||
|
||||
|
||||
private void OnFishingSetEquiped_OnRaised(FHandItem item)
|
||||
{
|
||||
if (item is FRod rod)
|
||||
{
|
||||
_isRodLayerEnabled = true;
|
||||
// var reel = Player.Rod.Reel;
|
||||
// _IK.SetBipedLeftHandIK(enabled: false, reel.FingersIKAnchor);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetLayerWeight(string layer, float weight)
|
||||
{
|
||||
_Animator.SetLayerWeight(_Animator.GetLayerIndex(layer), weight);
|
||||
}
|
||||
|
||||
private void PlayerFSMState_OnValueChanged(PlayerState state)
|
||||
{
|
||||
// switch (Player.Data.PreviousState)
|
||||
// {
|
||||
// case PlayerState.vehicle:
|
||||
// _IsInVehicle = false;
|
||||
// _Animator.SetBool(BoatDriving, value: false);
|
||||
// break;
|
||||
// case PlayerState.swiming:
|
||||
// _Animator.SetBool(IsSwiming, value: false);
|
||||
// break;
|
||||
// case PlayerState.preciseCastIdle:
|
||||
// _Animator.SetBool(PreciseIdle, value: false);
|
||||
// break;
|
||||
// case PlayerState.prepare:
|
||||
// _Animator.SetBool(RodArming, value: false);
|
||||
// break;
|
||||
// case PlayerState.casting:
|
||||
// _Animator.SetBool(ThrowFar, value: false);
|
||||
// break;
|
||||
// case PlayerState.collectFish:
|
||||
// _magicBlending.BlendAsset.globalWeight = 0f;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// switch (state)
|
||||
// {
|
||||
// switch (Player.Data.PreviousState)
|
||||
// {
|
||||
// case PlayerState.vehicle:
|
||||
// _IsInVehicle = false;
|
||||
// _Animator.SetBool(BoatDriving, value: false);
|
||||
// break;
|
||||
// case PlayerState.swiming:
|
||||
// _Animator.SetBool(IsSwiming, value: false);
|
||||
// break;
|
||||
// case PlayerState.preciseCastIdle:
|
||||
// _Animator.SetBool(PreciseIdle, value: false);
|
||||
// break;
|
||||
// case PlayerState.prepare:
|
||||
// _Animator.SetBool(RodArming, value: false);
|
||||
// break;
|
||||
// case PlayerState.casting:
|
||||
// _Animator.SetBool(ThrowFar, value: false);
|
||||
// break;
|
||||
// case PlayerState.collectFish:
|
||||
// _magicBlending.BlendAsset.globalWeight = 0f;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// switch (state)
|
||||
// {
|
||||
// case PlayerState.idle:
|
||||
// case PlayerState.move:
|
||||
// _Animator.SetBool(BaitInWater, value: false);
|
||||
// _Animator.SetBool(HeldRod, value: false);
|
||||
// _Animator.SetBool(ThrowFar, value: false);
|
||||
// _Animator.SetBool(RodArming, value: false);
|
||||
// break;
|
||||
// case PlayerState.prepare:
|
||||
// _Animator.SetBool(RodArming, value: true);
|
||||
// _Animator.SetBool(HeldRod, value: true);
|
||||
// break;
|
||||
// case PlayerState.fishing:
|
||||
// _Animator.SetBool(HeldRod, value: true);
|
||||
// _Animator.SetBool(BaitInWater, value: true);
|
||||
// break;
|
||||
// case PlayerState.vehicle:
|
||||
// _Animator.SetBool(BaitInWater, value: false);
|
||||
// _Animator.SetBool(HeldRod, value: false);
|
||||
// _Animator.SetBool(ThrowFar, value: false);
|
||||
// _Animator.SetBool(RodArming, value: false);
|
||||
// _Animator.SetBool(BoatDriving, value: true);
|
||||
// _IK.SetBipedLeftHandIK(enabled: true);
|
||||
// _IsInVehicle = true;
|
||||
// break;
|
||||
// case PlayerState.vehicleFishing:
|
||||
// _Animator.SetBool(BaitInWater, value: false);
|
||||
// _Animator.SetBool(HeldRod, value: false);
|
||||
// _Animator.SetBool(ThrowFar, value: false);
|
||||
// _Animator.SetBool(RodArming, value: false);
|
||||
// _IsInVehicle = true;
|
||||
// break;
|
||||
// case PlayerState.swiming:
|
||||
// _Animator.SetBool(IsSwiming, value: true);
|
||||
// break;
|
||||
// case PlayerState.collectFish:
|
||||
// _Animator.SetBool(BaitInWater, value: false);
|
||||
// _IK.SetAimIK(enabled: false);
|
||||
// _magicBlending.BlendAsset.globalWeight = 1f;
|
||||
// break;
|
||||
// case PlayerState.preciseCastIdle:
|
||||
// _Animator.SetBool(PreciseIdle, value: true);
|
||||
// break;
|
||||
// case PlayerState.casting:
|
||||
// case PlayerState.baitFlies:
|
||||
// case PlayerState.fight:
|
||||
// case PlayerState.fishView:
|
||||
// case PlayerState.throwFish:
|
||||
// case PlayerState.flyModeDebug:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
// if (Player.Data.State == PlayerState.swiming)
|
||||
// {
|
||||
// float value = Mathf.Lerp(_Animator.GetFloat(Forward), Player.Data.Speed / 2.5f,
|
||||
// Time.deltaTime * 5f);
|
||||
// float value2 = Mathf.Lerp(_Animator.GetFloat(Turn), Player.Data.RotationSpeed, Time.deltaTime * 5f);
|
||||
// _Animator.SetFloat(Forward, Mathf.Clamp01(value));
|
||||
// _Animator.SetFloat(Turn, Mathf.Clamp(value2, -1f, 1f));
|
||||
// }
|
||||
// else
|
||||
{
|
||||
float value3 = Mathf.Lerp(_Animator.GetFloat(Forward), Player.Data.Speed / 5f,
|
||||
Time.deltaTime * 20f);
|
||||
float value4 = Mathf.Lerp(_Animator.GetFloat(Turn), Player.Data.RotationSpeed, Time.deltaTime * 15f);
|
||||
_Animator.SetFloat(Forward, Mathf.Clamp01(value3));
|
||||
_Animator.SetFloat(Turn, Mathf.Clamp(value4, -1f, 1f));
|
||||
}
|
||||
|
||||
// var rod = Vector3.zero;
|
||||
// if (Player.Rod)
|
||||
// {
|
||||
// rod = Player.Rod.transform.position;
|
||||
// }
|
||||
|
||||
_Animator.SetBool(OnGroundHash, _IsInVehicle || Player.Data.IsGrounded);
|
||||
|
||||
|
||||
var isHandRodLayerEnabled = _isRodLayerEnabled && !Player.Data.IsLureRod ? 1 : 0;
|
||||
|
||||
float handRodLayerWeight = _Animator.GetLayerWeight(_Animator.GetLayerIndex(HandRodLayer));
|
||||
SetLayerWeight(HandRodLayer,
|
||||
Mathf.MoveTowards(handRodLayerWeight, isHandRodLayerEnabled, Time.deltaTime * 3f));
|
||||
|
||||
|
||||
var isLureRodLayerEnabled = _isRodLayerEnabled && Player.Data.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()
|
||||
{
|
||||
if (Player.Fsm.CurrentState is PlayerStateThrow playerStateThrow)
|
||||
{
|
||||
playerStateThrow.OnRodThrowStart();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 抛竿结束动画事件
|
||||
/// </summary>
|
||||
public void OnRodThrownEnd()
|
||||
{
|
||||
if (Player.Fsm.CurrentState is PlayerStateThrow playerStateThrow)
|
||||
{
|
||||
playerStateThrow.OnRodThrownEnd();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Player/PlayerAnimator.cs.meta
Normal file
3
Assets/Scripts/Fishing/Player/PlayerAnimator.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fc336a939c4416db623f3b4ae855265
|
||||
timeCreated: 1766470716
|
||||
29
Assets/Scripts/Fishing/Player/PlayerArm.cs
Normal file
29
Assets/Scripts/Fishing/Player/PlayerArm.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerArm : MonoBehaviour
|
||||
{
|
||||
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;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Player/PlayerArm.cs.meta
Normal file
3
Assets/Scripts/Fishing/Player/PlayerArm.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01ef40348d8b4d4da250acf0a921fc2a
|
||||
timeCreated: 1768660096
|
||||
25
Assets/Scripts/Fishing/Player/PlayerChest.cs
Normal file
25
Assets/Scripts/Fishing/Player/PlayerChest.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerChest : MonoBehaviour
|
||||
{
|
||||
private const int MaxFixEyeAngle = 15;
|
||||
private const int MinFixEyeAngle = -10;
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
FixArmAngle();
|
||||
}
|
||||
|
||||
private void FixArmAngle()
|
||||
{
|
||||
var angle = FPlayerData.Instance.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Player/PlayerChest.cs.meta
Normal file
3
Assets/Scripts/Fishing/Player/PlayerChest.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e152a74e74b54d17ace5403a1570e12a
|
||||
timeCreated: 1768668096
|
||||
156
Assets/Scripts/Fishing/Player/PlayerIK.cs
Normal file
156
Assets/Scripts/Fishing/Player/PlayerIK.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using RootMotion.FinalIK;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerIK : MonoBehaviour
|
||||
{
|
||||
public enum UpdateType
|
||||
{
|
||||
Update = 0,
|
||||
FixedUpdate = 1,
|
||||
LateUpdate = 2,
|
||||
Default = 3
|
||||
}
|
||||
|
||||
public UpdateType UpdateSelected;
|
||||
|
||||
// [SerializeField] private Transform _LeftHandTransform;
|
||||
|
||||
private LookAtIK _LookAtIK;
|
||||
|
||||
// private AimIK _AimIK;
|
||||
|
||||
// private FullBodyBipedIK _FullBodyIK;
|
||||
|
||||
// private ArmIK _ArmIK;
|
||||
|
||||
// private bool _isLeftHandEnabled;
|
||||
|
||||
// private bool _isRightHandEnabled;
|
||||
|
||||
// public bool isAimEnabled;
|
||||
|
||||
private bool _isFishingLeftArmEnabled;
|
||||
|
||||
[SerializeField] private float transitionWeightTimeScale = 1f;
|
||||
|
||||
// public Transform CurrentTarget => _FullBodyIK.solver.leftHandEffector.target;
|
||||
|
||||
// public Transform LeftHandTransform => _LeftHandTransform;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_LookAtIK = GetComponent<LookAtIK>();
|
||||
// _AimIK = GetComponent<AimIK>();
|
||||
// _FullBodyIK = GetComponent<FullBodyBipedIK>();
|
||||
// _ArmIK = GetComponent<ArmIK>();
|
||||
// SetAimIK(enabled: false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void SetBipedIK(bool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetFishingLeftArm(bool enabled)
|
||||
{
|
||||
_isFishingLeftArmEnabled = enabled;
|
||||
}
|
||||
|
||||
// public void SetFishingLeftArm(bool enabled, Transform target)
|
||||
// {
|
||||
// _isFishingLeftArmEnabled = enabled;
|
||||
// _ArmIK.solver.arm.target = target;
|
||||
// }
|
||||
|
||||
// public void SetBipedLeftHandIK(bool enabled, bool instant = false)
|
||||
// {
|
||||
// _isLeftHandEnabled = enabled;
|
||||
// if (instant)
|
||||
// {
|
||||
// _FullBodyIK.solver.leftArmMapping.weight = (enabled ? 1f : 0f);
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void SetBipedRightHandIK(bool enabled, bool instant = false)
|
||||
// {
|
||||
// _isRightHandEnabled = enabled;
|
||||
// if (instant)
|
||||
// {
|
||||
// _FullBodyIK.solver.rightArmMapping.weight = (enabled ? 1f : 0f);
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void SetBipedLeftHandIK(bool enabled, Transform target, bool instant = false)
|
||||
// {
|
||||
// _isLeftHandEnabled = enabled;
|
||||
// _FullBodyIK.solver.leftHandEffector.target = target;
|
||||
// if (instant)
|
||||
// {
|
||||
// _FullBodyIK.solver.leftArmMapping.weight = (enabled ? 1f : 0f);
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void SetBipedRightHandIK(bool enabled, Transform target, bool instant = false)
|
||||
// {
|
||||
// _isRightHandEnabled = enabled;
|
||||
// _FullBodyIK.solver.rightHandEffector.target = target;
|
||||
// if (instant)
|
||||
// {
|
||||
// _FullBodyIK.solver.rightArmMapping.weight = (enabled ? 1f : 0f);
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void SetAimIK(bool enabled)
|
||||
// {
|
||||
// isAimEnabled = enabled;
|
||||
// }
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (UpdateSelected == UpdateType.Update)
|
||||
{
|
||||
IKUpdateHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (UpdateSelected == UpdateType.FixedUpdate)
|
||||
{
|
||||
IKUpdateHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (UpdateSelected == UpdateType.LateUpdate)
|
||||
{
|
||||
IKUpdateHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private void IKUpdateHandler()
|
||||
{
|
||||
// _AimIK.UpdateSolverExternal();
|
||||
_LookAtIK.UpdateSolverExternal();
|
||||
// _FullBodyIK.UpdateSolverExternal();
|
||||
// _FullBodyIK.solver.Update();
|
||||
// _AimIK.solver.IKPositionWeight = Mathf.MoveTowards(_AimIK.solver.IKPositionWeight, isAimEnabled ? 1f : 0f,
|
||||
// Time.deltaTime * transitionWeightTimeScale);
|
||||
// _FullBodyIK.solver.leftArmMapping.weight = Mathf.MoveTowards(_FullBodyIK.solver.leftArmMapping.weight,
|
||||
// _isLeftHandEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
// _FullBodyIK.solver.rightArmMapping.weight = Mathf.MoveTowards(_FullBodyIK.solver.rightArmMapping.weight,
|
||||
// _isRightHandEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
// _FullBodyIK.solver.IKPositionWeight = Mathf.MoveTowards(_FullBodyIK.solver.IKPositionWeight,
|
||||
// _isLeftHandEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
// _ArmIK.solver.IKPositionWeight = Mathf.MoveTowards(_ArmIK.solver.IKPositionWeight,
|
||||
// _isFishingLeftArmEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
// _ArmIK.solver.IKRotationWeight = Mathf.MoveTowards(_ArmIK.solver.IKRotationWeight,
|
||||
// _isFishingLeftArmEnabled ? 1f : 0f, Time.deltaTime * transitionWeightTimeScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Player/PlayerIK.cs.meta
Normal file
3
Assets/Scripts/Fishing/Player/PlayerIK.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb36ecc5b1784d948837600cf18808cd
|
||||
timeCreated: 1765121426
|
||||
3
Assets/Scripts/Fishing/Player/States.meta
Normal file
3
Assets/Scripts/Fishing/Player/States.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3b57223c7f94237869524280afe1672
|
||||
timeCreated: 1768138483
|
||||
21
Assets/Scripts/Fishing/Player/States/PlayerStateBase.cs
Normal file
21
Assets/Scripts/Fishing/Player/States/PlayerStateBase.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public abstract class PlayerStateBase : FsmBaseState<FPlayer>
|
||||
{
|
||||
protected FPlayer Player => _owner;
|
||||
|
||||
/// <summary>
|
||||
/// 检查状态超时
|
||||
/// </summary>
|
||||
public void CheckStateTimeout(float time)
|
||||
{
|
||||
if (Time.time - EnterTime >= time)
|
||||
{
|
||||
Root.Start<PlayerStateIdle>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 080f1176c3ac4eefa37f615b22cac7ed
|
||||
timeCreated: 1768138530
|
||||
20
Assets/Scripts/Fishing/Player/States/PlayerStateFight.cs
Normal file
20
Assets/Scripts/Fishing/Player/States/PlayerStateFight.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace NBF
|
||||
{
|
||||
public class PlayerStateFight : PlayerStateBase
|
||||
{
|
||||
public override uint StateId => (uint)PlayerState.Fight;
|
||||
|
||||
protected override void onEnter()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void onExit()
|
||||
{
|
||||
}
|
||||
|
||||
protected override uint onUpdate()
|
||||
{
|
||||
return States.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0720dd0d400641bea639e36f169aafde
|
||||
timeCreated: 1768138922
|
||||
102
Assets/Scripts/Fishing/Player/States/PlayerStateFishing.cs
Normal file
102
Assets/Scripts/Fishing/Player/States/PlayerStateFishing.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 钓鱼中
|
||||
/// </summary>
|
||||
public class PlayerStateFishing : PlayerStateBase
|
||||
{
|
||||
public override uint StateId => (uint)PlayerState.Fishing;
|
||||
|
||||
protected override void onEnter()
|
||||
{
|
||||
Debug.LogError("enter PlayerStateFishing");
|
||||
_owner.ModelAsset.PlayerAnimator.BaitThrown = true;
|
||||
}
|
||||
|
||||
protected override void onExit()
|
||||
{
|
||||
_owner.ModelAsset.PlayerAnimator.BaitThrown = false;
|
||||
}
|
||||
|
||||
protected override uint onUpdate()
|
||||
{
|
||||
var ret = States.None;
|
||||
var isUpRod = false;
|
||||
var isSubLine = false;
|
||||
|
||||
if (InputManager.IsOp1)
|
||||
{
|
||||
if (!Player.Data.IsLureRod)
|
||||
{
|
||||
//抬杆
|
||||
isUpRod = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//收线
|
||||
isSubLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (InputManager.IsOp2)
|
||||
{
|
||||
if (Player.Data.IsLureRod)
|
||||
{
|
||||
//抬杆
|
||||
isUpRod = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Player.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
|
||||
if (isUpRod || Player.ModelAsset.PlayerAnimator.FishingUp > 0)
|
||||
{
|
||||
var upForce = 1;
|
||||
var addNum = upForce * Time.deltaTime;
|
||||
if (!isUpRod)
|
||||
{
|
||||
addNum *= -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
addNum *= 0.5f;
|
||||
}
|
||||
|
||||
// Debug.Log($"addNum={addNum}");
|
||||
Player.ModelAsset.PlayerAnimator.FishingUp += addNum;
|
||||
// Debug.LogError($"ishingFinal={Player.ModelAsset.PlayerAnimator.FishingUp}");
|
||||
if (Player.ModelAsset.PlayerAnimator.FishingUp >= 1)
|
||||
{
|
||||
Player.ModelAsset.PlayerAnimator.FishingUp = 1;
|
||||
}
|
||||
else if (Player.ModelAsset.PlayerAnimator.FishingUp < 0)
|
||||
{
|
||||
Player.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
}
|
||||
|
||||
if (Player.ModelAsset.PlayerAnimator.FishingUp >= 0.8f)
|
||||
{
|
||||
ret = CheckTackFish();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Player.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#region 检查上鱼或者返回待机
|
||||
|
||||
private uint CheckTackFish()
|
||||
{
|
||||
return (uint)PlayerState.Idle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6953fd92b2c54c6e846a0363520a9010
|
||||
timeCreated: 1768138900
|
||||
44
Assets/Scripts/Fishing/Player/States/PlayerStateIdle.cs
Normal file
44
Assets/Scripts/Fishing/Player/States/PlayerStateIdle.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using NBC;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 闲置中
|
||||
/// </summary>
|
||||
public class PlayerStateIdle : PlayerStateBase
|
||||
{
|
||||
public override uint StateId => (uint)PlayerState.Idle;
|
||||
private bool _nextState = false;
|
||||
|
||||
protected override void onEnter()
|
||||
{
|
||||
Log.Info("enter PlayerStateIdle");
|
||||
_nextState = false;
|
||||
InputManager.OnOp1Action += OnOp1Action;
|
||||
}
|
||||
|
||||
private void OnOp1Action(bool performed)
|
||||
{
|
||||
if (!Player.Rod) return;
|
||||
if (performed)
|
||||
{
|
||||
_nextState = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void onExit()
|
||||
{
|
||||
InputManager.OnOp1Action -= OnOp1Action;
|
||||
}
|
||||
|
||||
protected override uint onUpdate()
|
||||
{
|
||||
if (_nextState)
|
||||
{
|
||||
return (uint)PlayerState.Prepare;
|
||||
}
|
||||
|
||||
return States.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6146dcfbaf54972ac75c8115041ed3e
|
||||
timeCreated: 1768138510
|
||||
76
Assets/Scripts/Fishing/Player/States/PlayerStatePrepare.cs
Normal file
76
Assets/Scripts/Fishing/Player/States/PlayerStatePrepare.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 准备抛竿中
|
||||
/// </summary>
|
||||
public class PlayerStatePrepare : PlayerStateBase
|
||||
{
|
||||
public override uint StateId => (uint)PlayerState.Prepare;
|
||||
|
||||
public enum Phase
|
||||
{
|
||||
/// <summary>
|
||||
/// 蓄力
|
||||
/// </summary>
|
||||
Charged,
|
||||
|
||||
/// <summary>
|
||||
/// 确认蓄力结果
|
||||
/// </summary>
|
||||
Confirm,
|
||||
}
|
||||
|
||||
public Phase Stage = Phase.Charged;
|
||||
public float ChargedProgress;
|
||||
|
||||
protected override void onEnter()
|
||||
{
|
||||
Log.Info("enter PlayerStatePrepare");
|
||||
Stage = Phase.Charged;
|
||||
Player.ModelAsset.PlayerAnimator.PrepareThrow = true;
|
||||
Player.ModelAsset.PlayerAnimator.FishingUp = 0;
|
||||
}
|
||||
|
||||
protected override uint onUpdate()
|
||||
{
|
||||
if (Stage == Phase.Charged)
|
||||
{
|
||||
ThrowPowerCharged();
|
||||
}
|
||||
else if (Stage == Phase.Confirm)
|
||||
{
|
||||
//确认蓄力结果,
|
||||
Debug.Log($"确认蓄力结果,ChargedProgress={ChargedProgress}");
|
||||
Params.Add(ChargedProgress);
|
||||
return (uint)PlayerState.Throw;
|
||||
}
|
||||
|
||||
return base.onUpdate();
|
||||
}
|
||||
|
||||
|
||||
#region 蓄力中
|
||||
|
||||
private void ThrowPowerCharged()
|
||||
{
|
||||
if (ChargedProgress < 1)
|
||||
{
|
||||
ChargedProgress += Time.deltaTime;
|
||||
}
|
||||
else if (ChargedProgress > 1)
|
||||
{
|
||||
ChargedProgress = 1;
|
||||
}
|
||||
|
||||
if (!InputManager.IsOp1)
|
||||
{
|
||||
Stage = Phase.Confirm;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1301b70435cd44c8ba3cc6085f35a782
|
||||
timeCreated: 1768138823
|
||||
100
Assets/Scripts/Fishing/Player/States/PlayerStateThrow.cs
Normal file
100
Assets/Scripts/Fishing/Player/States/PlayerStateThrow.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using NBC;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
/// <summary>
|
||||
/// 抛竿中
|
||||
/// </summary>
|
||||
public class PlayerStateThrow : PlayerStateBase
|
||||
{
|
||||
public override uint StateId => (uint)PlayerState.Throw;
|
||||
|
||||
// public enum Phase
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// 等待动画事件回调
|
||||
// /// </summary>
|
||||
// Waiting,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 前摇动画
|
||||
// /// </summary>
|
||||
// AnimBegin,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 抛线动画
|
||||
// /// </summary>
|
||||
// ThrowAnim,
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 结束
|
||||
// /// </summary>
|
||||
// Done,
|
||||
// ErrorDone
|
||||
// }
|
||||
//
|
||||
// public Phase Stage = Phase.Waiting;
|
||||
private bool _nextState = false;
|
||||
public float ChargedProgress;
|
||||
|
||||
protected override void onEnter()
|
||||
{
|
||||
Log.Info("enter PlayerStateThrow");
|
||||
_owner.ModelAsset.PlayerAnimator.StartThrow = true;
|
||||
|
||||
ChargedProgress = (float)Params.Get(0);
|
||||
Debug.Log($"PlayerThrow ChargedProgress={ChargedProgress}");
|
||||
_nextState = false;
|
||||
// Stage = Phase.Waiting;
|
||||
|
||||
// _owner.Gears.Reel?.Unlock();
|
||||
}
|
||||
|
||||
protected override uint onUpdate()
|
||||
{
|
||||
CheckStateTimeout(10);
|
||||
if (_nextState)
|
||||
{
|
||||
return (uint)PlayerState.Fishing;
|
||||
}
|
||||
|
||||
return base.onUpdate();
|
||||
}
|
||||
|
||||
// IEnumerator ThrowCoroutine(float distance)
|
||||
// {
|
||||
// float startLength = 0.5f;
|
||||
// Debug.Log($"REST LENGTH : {rope.restLength}");
|
||||
// do
|
||||
// {
|
||||
// float a = Vector3.Distance(rodTipTarget.position, attachedBody.transform.position);
|
||||
// attachedBody.RBody.AddForce(playerForward.Value, ForceMode.VelocityChange);
|
||||
// startLength = Mathf.Max(a, startLength);
|
||||
// UnwindLine(attachedBody.RBody.linearVelocity.magnitude * Time.deltaTime);
|
||||
// yield return null;
|
||||
// }
|
||||
// while ((bool)isBailOpen);
|
||||
// }
|
||||
|
||||
#region 动画回调
|
||||
|
||||
/// <summary>
|
||||
/// 抛竿动画事件
|
||||
/// </summary>
|
||||
public void OnRodThrowStart()
|
||||
{
|
||||
Debug.LogError("OnRodThrowStart");
|
||||
_owner.ModelAsset.PlayerAnimator.PrepareThrow = false;
|
||||
_owner.ModelAsset.PlayerAnimator.StartThrow = false;
|
||||
}
|
||||
|
||||
public void OnRodThrownEnd()
|
||||
{
|
||||
Debug.LogError("OnRodThrownEnd");
|
||||
_nextState = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a0b4bc6f668446cab7baf752da60477
|
||||
timeCreated: 1768138870
|
||||
2813
Assets/Scripts/Fishing/PlayerInputControl.cs
Normal file
2813
Assets/Scripts/Fishing/PlayerInputControl.cs
Normal file
File diff suppressed because it is too large
Load Diff
2
Assets/Scripts/Fishing/PlayerInputControl.cs.meta
Normal file
2
Assets/Scripts/Fishing/PlayerInputControl.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b245d0b3de2c4fb4aa46602e8a5b1416
|
||||
3
Assets/Scripts/Fishing/Rope.meta
Normal file
3
Assets/Scripts/Fishing/Rope.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1330e7f73f804eea8ae09724f6bb1039
|
||||
timeCreated: 1766759962
|
||||
55
Assets/Scripts/Fishing/Rope/RodLine.cs
Normal file
55
Assets/Scripts/Fishing/Rope/RodLine.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// using Obi;
|
||||
using UnityEngine;
|
||||
|
||||
public class RodLine : MonoBehaviour
|
||||
{
|
||||
// private ObiRope obiRope;
|
||||
|
||||
private LineRenderer lineRenderer;
|
||||
|
||||
private Transform[] points;
|
||||
|
||||
public void GenerateLineRendererRope(Transform[] points, float thickness)
|
||||
{
|
||||
if (points.Length < 2)
|
||||
{
|
||||
Debug.LogError("LineRenderer requires at least two points.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.points = points;
|
||||
if (lineRenderer == null)
|
||||
{
|
||||
lineRenderer = base.gameObject.GetComponent<LineRenderer>();
|
||||
if (lineRenderer == null)
|
||||
{
|
||||
lineRenderer = base.gameObject.AddComponent<LineRenderer>();
|
||||
}
|
||||
}
|
||||
|
||||
lineRenderer.positionCount = points.Length;
|
||||
lineRenderer.startWidth = thickness;
|
||||
lineRenderer.endWidth = thickness;
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
lineRenderer.SetPosition(i, points[i].position);
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (lineRenderer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < points.Length; i++)
|
||||
{
|
||||
var point = points[i];
|
||||
if (point)
|
||||
{
|
||||
lineRenderer.SetPosition(i, point.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Rope/RodLine.cs.meta
Normal file
3
Assets/Scripts/Fishing/Rope/RodLine.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5625b86b9e4b4482b82d83b962d0c873
|
||||
timeCreated: 1766759973
|
||||
669
Assets/Scripts/Fishing/Rope/Rope.cs
Normal file
669
Assets/Scripts/Fishing/Rope/Rope.cs
Normal file
@@ -0,0 +1,669 @@
|
||||
using System;
|
||||
using NBF;
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(LineRenderer))]
|
||||
public class Rope : MonoBehaviour
|
||||
{
|
||||
[Header("Anchors")] [SerializeField] public Rigidbody startAnchor;
|
||||
[SerializeField] public Rigidbody endAnchor;
|
||||
|
||||
/// <summary>鱼线宽度倍数</summary>
|
||||
public int LineMultiple = 1;
|
||||
|
||||
[Header("Physics (Dynamic Nodes, Fixed Segment Len)")] [SerializeField, Min(0.01f), Tooltip("物理每段固定长度(越小越细致越耗)")]
|
||||
private float physicsSegmentLen = 0.15f;
|
||||
|
||||
[SerializeField, Range(2, 200)] private int minPhysicsNodes = 12;
|
||||
|
||||
[SerializeField, Range(2, 400), Tooltip("物理节点上限(仅用于性能保护;与“最大长度不限制”不是一回事)")]
|
||||
private int maxPhysicsNodes = 120;
|
||||
|
||||
[SerializeField] private float gravityStrength = 2.0f;
|
||||
[SerializeField, Range(0f, 1f)] private float velocityDampen = 0.95f;
|
||||
|
||||
[SerializeField, Range(0.0f, 1.0f), Tooltip("约束修正强度,越大越硬。0.6~0.9 常用")]
|
||||
private float stiffness = 0.8f;
|
||||
|
||||
[SerializeField, Range(1, 80), Tooltip("迭代次数。鱼线 10~30 通常够用")]
|
||||
private int iterations = 20;
|
||||
|
||||
[Header("Length Control (No Min/Max Clamp)")]
|
||||
[Tooltip("初始总长度(米)。如果为 0,则用 physicsSegmentLen*(minPhysicsNodes-1) 作为初始长度")]
|
||||
[SerializeField, Min(0f)]
|
||||
private float initialLength = 0f;
|
||||
|
||||
[Tooltip("长度变化平滑时间(越小越跟手,越大越稳)")] [SerializeField, Min(0.0001f)]
|
||||
private float lengthSmoothTime = 0.15f;
|
||||
|
||||
[Tooltip("当长度在变化时,额外把速度压掉一些(防抖)。0=不额外处理,1=变化时几乎清速度(建议只在收线生效)")] [SerializeField, Range(0f, 1f)]
|
||||
private float lengthChangeVelocityKill = 0.6f;
|
||||
|
||||
[Tooltip("允许的最小松弛余量(避免目标长度刚好等于锚点距离时抖动)")] [SerializeField, Min(0f)]
|
||||
private float minSlack = 0.002f;
|
||||
|
||||
[Header("Head Segment Clamp")] [Tooltip("第一段(起点->第1节点)允许的最小长度,避免收线时第一段被压到0导致数值炸")] [SerializeField, Min(0.0001f)]
|
||||
private float headMinLen = 0.01f;
|
||||
|
||||
[Header("Node Count Stability")] [SerializeField, Tooltip("节点数切换迟滞(米)。避免长度在临界点抖动导致节点数来回跳 -> 卡顿")]
|
||||
private float nodeHysteresis = 0.05f;
|
||||
|
||||
[Header("Simple Ground/Water Constraint (Cheap)")] [SerializeField]
|
||||
private bool constrainToGround = true;
|
||||
|
||||
[SerializeField] private LayerMask groundMask = ~0;
|
||||
[SerializeField, Min(0f)] private float groundRadius = 0.01f;
|
||||
[SerializeField, Min(0f)] private float groundCastHeight = 1.0f;
|
||||
[SerializeField, Min(0.01f)] private float groundCastDistance = 2.5f;
|
||||
|
||||
[SerializeField, Range(1, 8), Tooltip("每隔多少个节点做一次地面检测;越大越省")]
|
||||
private int groundSampleStep = 3;
|
||||
|
||||
[SerializeField, Tooltip("未采样的点用插值还是直接拷贝邻近采样值")]
|
||||
private bool groundInterpolate = true;
|
||||
|
||||
[SerializeField, Range(1, 8), Tooltip("每隔多少次FixedUpdate更新一次地面约束")]
|
||||
private int groundUpdateEvery = 2;
|
||||
private int _groundFrameCounter;
|
||||
|
||||
|
||||
[Header("Render (High Resolution)")] [SerializeField, Min(1), Tooltip("静止时每段物理线段插值加密数量(越大越顺,越耗)")]
|
||||
private int renderSubdivisionsIdle = 6;
|
||||
|
||||
[SerializeField, Min(1), Tooltip("甩动时每段物理线段插值加密数量(动态降LOD以防卡顿)")]
|
||||
private int renderSubdivisionsMoving = 2;
|
||||
|
||||
[SerializeField, Min(0f), Tooltip("平均速度超过该阈值认为在甩动(用于动态降 subdiv)")]
|
||||
private float movingSpeedThreshold = 2.0f;
|
||||
|
||||
[SerializeField, Tooltip("是否使用 Catmull-Rom 平滑(开启更顺,但更耗)")]
|
||||
private bool smooth = true;
|
||||
|
||||
[SerializeField, Min(0.0001f)] private float lineWidth = 0.001f;
|
||||
|
||||
[Header("Air Drag (Stable)")] [SerializeField, Range(0f, 5f), Tooltip("空气阻力(Y向),指数衰减,越大越不飘")]
|
||||
private float airDrag = 0.9f;
|
||||
|
||||
[SerializeField, Range(0f, 2f), Tooltip("横向额外阻力(XZ),指数衰减,越大越不左右飘")]
|
||||
private float airDragXZ = 0.6f;
|
||||
|
||||
private LineRenderer _lineRenderer;
|
||||
|
||||
// physics
|
||||
private int _physicsNodes;
|
||||
private Vector3[] _pCurr;
|
||||
private Vector3[] _pPrev;
|
||||
|
||||
// render (一次性分配到最大,后续不再 new)
|
||||
private Vector3[] _rPoints;
|
||||
private int _rCapacity;
|
||||
|
||||
private Vector3 _gravity;
|
||||
|
||||
// length control runtime
|
||||
private float _targetLength;
|
||||
private float _currentLength;
|
||||
private float _lengthSmoothVel;
|
||||
|
||||
// rest length head
|
||||
private float _headRestLen;
|
||||
|
||||
// node stability
|
||||
private int _lastDesiredNodes = 0;
|
||||
|
||||
// caches
|
||||
private Transform _startTr;
|
||||
private Transform _endTr;
|
||||
|
||||
// precomputed
|
||||
private float _dt;
|
||||
private float _dt2;
|
||||
private float _kY;
|
||||
private float _kXZ;
|
||||
|
||||
private FRod _rod;
|
||||
public void Init(FRod rod) => _rod = rod;
|
||||
|
||||
// Catmull t caches(只缓存 idle/moving 两档,减少每帧重复乘法)
|
||||
private struct TCaches
|
||||
{
|
||||
public float[] t;
|
||||
public float[] t2;
|
||||
public float[] t3;
|
||||
}
|
||||
|
||||
private TCaches _tIdle;
|
||||
private TCaches _tMoving;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_lineRenderer = GetComponent<LineRenderer>();
|
||||
_gravity = new Vector3(0f, -gravityStrength, 0f);
|
||||
|
||||
_startTr = startAnchor ? startAnchor.transform : null;
|
||||
_endTr = endAnchor ? endAnchor.transform : null;
|
||||
|
||||
InitLengthSystem();
|
||||
AllocateAndInitNodes();
|
||||
|
||||
// ✅ 渲染点一次性分配到最大: (maxNodes-1)*idle + 1
|
||||
int maxSubdiv = Mathf.Max(1, renderSubdivisionsIdle);
|
||||
_rCapacity = (maxPhysicsNodes - 1) * maxSubdiv + 1;
|
||||
_rPoints = new Vector3[_rCapacity];
|
||||
|
||||
BuildTCaches(renderSubdivisionsIdle, ref _tIdle);
|
||||
BuildTCaches(renderSubdivisionsMoving, ref _tMoving);
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
renderSubdivisionsIdle = Mathf.Max(renderSubdivisionsIdle, 1);
|
||||
renderSubdivisionsMoving = Mathf.Max(renderSubdivisionsMoving, 1);
|
||||
iterations = Mathf.Clamp(iterations, 1, 80);
|
||||
groundCastDistance = Mathf.Max(groundCastDistance, 0.01f);
|
||||
groundCastHeight = Mathf.Max(groundCastHeight, 0f);
|
||||
lineWidth = Mathf.Max(lineWidth, 0.0001f);
|
||||
|
||||
lengthSmoothTime = Mathf.Max(lengthSmoothTime, 0.0001f);
|
||||
|
||||
physicsSegmentLen = Mathf.Max(physicsSegmentLen, 0.01f);
|
||||
minPhysicsNodes = Mathf.Max(minPhysicsNodes, 2);
|
||||
maxPhysicsNodes = Mathf.Max(maxPhysicsNodes, minPhysicsNodes);
|
||||
|
||||
headMinLen = Mathf.Max(headMinLen, 0.0001f);
|
||||
nodeHysteresis = Mathf.Max(0f, nodeHysteresis);
|
||||
}
|
||||
|
||||
private void InitLengthSystem()
|
||||
{
|
||||
float defaultLen = physicsSegmentLen * (Mathf.Max(minPhysicsNodes, 2) - 1);
|
||||
_currentLength = (initialLength > 0f) ? initialLength : defaultLen;
|
||||
_targetLength = _currentLength;
|
||||
}
|
||||
|
||||
private void AllocateAndInitNodes()
|
||||
{
|
||||
_physicsNodes = Mathf.Clamp(ComputeDesiredNodesStable(_currentLength), 2, maxPhysicsNodes);
|
||||
|
||||
_pCurr = new Vector3[maxPhysicsNodes];
|
||||
_pPrev = new Vector3[maxPhysicsNodes];
|
||||
|
||||
Vector3 start = startAnchor ? startAnchor.position : transform.position;
|
||||
Vector3 dir = Vector3.down;
|
||||
|
||||
for (int i = 0; i < _physicsNodes; i++)
|
||||
{
|
||||
Vector3 pos = start + dir * (physicsSegmentLen * i);
|
||||
_pCurr[i] = pos;
|
||||
_pPrev[i] = pos;
|
||||
}
|
||||
|
||||
UpdateHeadRestLenFromCurrentLength();
|
||||
|
||||
if (startAnchor && endAnchor)
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private int ComputeDesiredNodes(float lengthMeters)
|
||||
{
|
||||
int desired = Mathf.FloorToInt(Mathf.Max(0f, lengthMeters) / physicsSegmentLen) + 1;
|
||||
desired = Mathf.Clamp(desired, minPhysicsNodes, maxPhysicsNodes);
|
||||
return desired;
|
||||
}
|
||||
|
||||
private int ComputeDesiredNodesStable(float lengthMeters)
|
||||
{
|
||||
int desired = ComputeDesiredNodes(lengthMeters);
|
||||
|
||||
if (_lastDesiredNodes == 0)
|
||||
{
|
||||
_lastDesiredNodes = desired;
|
||||
return desired;
|
||||
}
|
||||
|
||||
if (desired == _lastDesiredNodes)
|
||||
return desired;
|
||||
|
||||
float boundary = (_lastDesiredNodes - 1) * physicsSegmentLen;
|
||||
if (Mathf.Abs(lengthMeters - boundary) < nodeHysteresis)
|
||||
return _lastDesiredNodes;
|
||||
|
||||
_lastDesiredNodes = desired;
|
||||
return desired;
|
||||
}
|
||||
|
||||
public void SetTargetLength(float lengthMeters) => _targetLength = Mathf.Max(0f, lengthMeters);
|
||||
public float GetCurrentLength() => _currentLength;
|
||||
public float GetTargetLength() => _targetLength;
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (!startAnchor || !endAnchor) return;
|
||||
|
||||
// cache dt
|
||||
_dt = Time.fixedDeltaTime;
|
||||
if (_dt < 1e-6f) _dt = 1e-6f;
|
||||
_dt2 = _dt * _dt;
|
||||
|
||||
// gravity
|
||||
_gravity.y = -gravityStrength;
|
||||
|
||||
// drag caches(exp 比较贵,但这里每 FixedUpdate 一次,OK)
|
||||
_kY = Mathf.Exp(-airDrag * _dt);
|
||||
_kXZ = Mathf.Exp(-airDragXZ * _dt);
|
||||
|
||||
UpdateLengthSmooth();
|
||||
UpdateNodesFromLength();
|
||||
UpdateHeadRestLenFromCurrentLength();
|
||||
|
||||
Simulate_VerletFast();
|
||||
|
||||
// anchors
|
||||
LockAnchorsHard();
|
||||
|
||||
// constraints
|
||||
for (int it = 0; it < iterations; it++)
|
||||
SolveDistanceConstraints_HeadOnly_Fast();
|
||||
|
||||
LockAnchorsHard();
|
||||
|
||||
if (constrainToGround)
|
||||
{
|
||||
_groundFrameCounter++;
|
||||
if (_groundFrameCounter >= groundUpdateEvery)
|
||||
{
|
||||
_groundFrameCounter = 0;
|
||||
ConstrainToGround();
|
||||
}
|
||||
}
|
||||
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (!startAnchor || !endAnchor || _pCurr == null || _physicsNodes < 2) return;
|
||||
|
||||
int last = _physicsNodes - 1;
|
||||
|
||||
// 用缓存 transform,避免多次属性链
|
||||
Vector3 s = _startTr.position;
|
||||
Vector3 e = _endTr.position;
|
||||
|
||||
_pCurr[0] = s;
|
||||
_pPrev[0] = s;
|
||||
_pCurr[last] = e;
|
||||
_pPrev[last] = e;
|
||||
|
||||
DrawHighResLine_Fast();
|
||||
}
|
||||
|
||||
private void UpdateLengthSmooth()
|
||||
{
|
||||
float minFeasible = 0.01f;
|
||||
float desired = Mathf.Max(_targetLength, minFeasible);
|
||||
|
||||
_currentLength = Mathf.SmoothDamp(
|
||||
_currentLength,
|
||||
desired,
|
||||
ref _lengthSmoothVel,
|
||||
lengthSmoothTime,
|
||||
Mathf.Infinity,
|
||||
Time.fixedDeltaTime
|
||||
);
|
||||
}
|
||||
|
||||
private void UpdateNodesFromLength()
|
||||
{
|
||||
int desired = ComputeDesiredNodesStable(_currentLength);
|
||||
desired = Mathf.Clamp(desired, 2, maxPhysicsNodes);
|
||||
if (desired == _physicsNodes) return;
|
||||
|
||||
if (desired > _physicsNodes) AddNodesAtStart(desired - _physicsNodes);
|
||||
else RemoveNodesAtStart(_physicsNodes - desired);
|
||||
|
||||
_physicsNodes = desired;
|
||||
}
|
||||
|
||||
private void AddNodesAtStart(int addCount)
|
||||
{
|
||||
if (addCount <= 0) return;
|
||||
|
||||
int oldCount = _physicsNodes;
|
||||
int newCount = Mathf.Min(oldCount + addCount, maxPhysicsNodes);
|
||||
addCount = newCount - oldCount;
|
||||
if (addCount <= 0) return;
|
||||
|
||||
Array.Copy(_pCurr, 1, _pCurr, 1 + addCount, oldCount - 1);
|
||||
Array.Copy(_pPrev, 1, _pPrev, 1 + addCount, oldCount - 1);
|
||||
|
||||
Vector3 s = _startTr ? _startTr.position : startAnchor.position;
|
||||
|
||||
Vector3 dir = Vector3.down;
|
||||
int firstOld = 1 + addCount;
|
||||
if (oldCount >= 2 && firstOld < maxPhysicsNodes)
|
||||
{
|
||||
Vector3 toOld1 = (_pCurr[firstOld] - s);
|
||||
float sq = toOld1.sqrMagnitude;
|
||||
if (sq > 1e-6f) dir = toOld1 / Mathf.Sqrt(sq);
|
||||
}
|
||||
|
||||
// inherit displacement (Verlet)
|
||||
Vector3 inheritDisp = Vector3.zero;
|
||||
if (oldCount >= 2 && firstOld < maxPhysicsNodes)
|
||||
inheritDisp = (_pCurr[firstOld] - _pPrev[firstOld]);
|
||||
|
||||
for (int k = 1; k <= addCount; k++)
|
||||
{
|
||||
Vector3 pos = s + dir * (physicsSegmentLen * k);
|
||||
_pCurr[k] = pos;
|
||||
_pPrev[k] = pos - inheritDisp; // 保持动感
|
||||
}
|
||||
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private void RemoveNodesAtStart(int removeCount)
|
||||
{
|
||||
if (removeCount <= 0) return;
|
||||
|
||||
int oldCount = _physicsNodes;
|
||||
int newCount = Mathf.Max(oldCount - removeCount, 2);
|
||||
removeCount = oldCount - newCount;
|
||||
if (removeCount <= 0) return;
|
||||
|
||||
Array.Copy(_pCurr, 1 + removeCount, _pCurr, 1, newCount - 2);
|
||||
Array.Copy(_pPrev, 1 + removeCount, _pPrev, 1, newCount - 2);
|
||||
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private void UpdateHeadRestLenFromCurrentLength()
|
||||
{
|
||||
int fixedSegCount = Mathf.Max(0, _physicsNodes - 2);
|
||||
float baseLen = fixedSegCount * physicsSegmentLen;
|
||||
|
||||
_headRestLen = _currentLength - baseLen;
|
||||
_headRestLen = Mathf.Clamp(_headRestLen, headMinLen, physicsSegmentLen * 1.5f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ✅ 更快的 Verlet:去掉 /dt 和 *dt 抵消的无效计算
|
||||
/// </summary>
|
||||
private void Simulate_VerletFast()
|
||||
{
|
||||
// displacement = curr - prev
|
||||
// next = curr + displacement*drag*dampen + gravity*dt^2
|
||||
for (int i = 1; i < _physicsNodes - 1; i++)
|
||||
{
|
||||
Vector3 disp = _pCurr[i] - _pPrev[i];
|
||||
|
||||
disp.x *= _kXZ;
|
||||
disp.z *= _kXZ;
|
||||
disp.y *= _kY;
|
||||
|
||||
disp *= velocityDampen;
|
||||
|
||||
Vector3 next = _pCurr[i] + disp + _gravity * _dt2;
|
||||
|
||||
_pPrev[i] = _pCurr[i];
|
||||
_pCurr[i] = next;
|
||||
}
|
||||
}
|
||||
|
||||
private void LockAnchorsHard()
|
||||
{
|
||||
if (!startAnchor || !endAnchor || _pCurr == null || _pPrev == null || _physicsNodes < 2) return;
|
||||
|
||||
Vector3 s = _startTr ? _startTr.position : startAnchor.position;
|
||||
Vector3 e = _endTr ? _endTr.position : endAnchor.position;
|
||||
|
||||
_pCurr[0] = s;
|
||||
_pPrev[0] = s - startAnchor.linearVelocity * _dt;
|
||||
|
||||
int last = _physicsNodes - 1;
|
||||
_pCurr[last] = e;
|
||||
_pPrev[last] = e - endAnchor.linearVelocity * _dt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ✅ 约束:减少临时变量、用 sqrMagnitude + invDist
|
||||
/// </summary>
|
||||
private void SolveDistanceConstraints_HeadOnly_Fast()
|
||||
{
|
||||
int last = _physicsNodes - 1;
|
||||
|
||||
for (int i = 0; i < last; i++)
|
||||
{
|
||||
float rest = (i == 0) ? _headRestLen : physicsSegmentLen;
|
||||
|
||||
Vector3 a = _pCurr[i];
|
||||
Vector3 b = _pCurr[i + 1];
|
||||
|
||||
Vector3 delta = b - a;
|
||||
float sq = delta.sqrMagnitude;
|
||||
if (sq < 1e-12f) continue;
|
||||
|
||||
float dist = Mathf.Sqrt(sq);
|
||||
float diff = (dist - rest) / dist; // = 1 - rest/dist
|
||||
Vector3 corr = delta * (diff * stiffness);
|
||||
|
||||
// i==0 锚点固定;last 锚点固定
|
||||
if (i != 0) _pCurr[i] = a + corr * 0.5f;
|
||||
if (i + 1 != last) _pCurr[i + 1] = b - corr * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
// private void ConstrainToGround()
|
||||
// {
|
||||
// if (groundMask == 0) return;
|
||||
//
|
||||
// // RaycastHit 是 struct,这里不会 GC
|
||||
// for (int i = 1; i < _physicsNodes - 1; i++)
|
||||
// {
|
||||
// Vector3 p = _pCurr[i];
|
||||
// Vector3 origin = p + Vector3.up * groundCastHeight;
|
||||
//
|
||||
// if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, groundCastDistance, groundMask,
|
||||
// QueryTriggerInteraction.Ignore))
|
||||
// {
|
||||
// float minY = hit.point.y + groundRadius;
|
||||
// if (p.y < minY) p.y = minY;
|
||||
// }
|
||||
//
|
||||
// _pCurr[i] = p;
|
||||
// }
|
||||
// }
|
||||
|
||||
private void ConstrainToGround()
|
||||
{
|
||||
if (groundMask == 0) return;
|
||||
|
||||
int last = _physicsNodes - 1;
|
||||
int step = Mathf.Max(1, groundSampleStep);
|
||||
|
||||
// 记录采样点的“最低允许Y”
|
||||
// 不想分配数组就用局部变量滚动插值
|
||||
int prevSampleIdx = 1;
|
||||
float prevMinY = SampleMinY(_pCurr[prevSampleIdx]);
|
||||
|
||||
// 把采样点先处理掉
|
||||
ApplyMinY(prevSampleIdx, prevMinY);
|
||||
|
||||
for (int i = 1 + step; i < last; i += step)
|
||||
{
|
||||
float nextMinY = SampleMinY(_pCurr[i]);
|
||||
ApplyMinY(i, nextMinY);
|
||||
|
||||
if (groundInterpolate)
|
||||
{
|
||||
// 在两个采样点之间插值 minY(视觉更平滑)
|
||||
int a = prevSampleIdx;
|
||||
int b = i;
|
||||
int span = b - a;
|
||||
for (int j = 1; j < span; j++)
|
||||
{
|
||||
int idx = a + j;
|
||||
float t = j / (float)span;
|
||||
float minY = Mathf.Lerp(prevMinY, nextMinY, t);
|
||||
ApplyMinY(idx, minY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 直接用 prevMinY 填充中间点(更省)
|
||||
for (int idx = prevSampleIdx + 1; idx < i; idx++)
|
||||
ApplyMinY(idx, prevMinY);
|
||||
}
|
||||
|
||||
prevSampleIdx = i;
|
||||
prevMinY = nextMinY;
|
||||
}
|
||||
|
||||
// 尾巴剩余部分用最后一个采样值填
|
||||
for (int i = prevSampleIdx + 1; i < last; i++)
|
||||
ApplyMinY(i, prevMinY);
|
||||
}
|
||||
|
||||
private float SampleMinY(Vector3 p)
|
||||
{
|
||||
Vector3 origin = p + Vector3.up * groundCastHeight;
|
||||
if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, groundCastDistance, groundMask,
|
||||
QueryTriggerInteraction.Ignore))
|
||||
return hit.point.y + groundRadius;
|
||||
|
||||
// 没命中就不抬(返回极小值)
|
||||
return float.NegativeInfinity;
|
||||
}
|
||||
|
||||
private void ApplyMinY(int i, float minY)
|
||||
{
|
||||
if (float.IsNegativeInfinity(minY)) return;
|
||||
Vector3 p = _pCurr[i];
|
||||
if (p.y < minY) p.y = minY;
|
||||
_pCurr[i] = p;
|
||||
}
|
||||
|
||||
private void DrawHighResLine_Fast()
|
||||
{
|
||||
if (_pCurr == null || _physicsNodes < 2) return;
|
||||
|
||||
float w = lineWidth * LineMultiple;
|
||||
_lineRenderer.startWidth = w;
|
||||
_lineRenderer.endWidth = w;
|
||||
|
||||
if (!smooth)
|
||||
{
|
||||
_lineRenderer.positionCount = _physicsNodes;
|
||||
_lineRenderer.SetPositions(_pCurr);
|
||||
return;
|
||||
}
|
||||
|
||||
int subdiv = PickRenderSubdivisions_Fast();
|
||||
TCaches tc = (subdiv == renderSubdivisionsMoving) ? _tMoving : _tIdle;
|
||||
|
||||
int needed = (_physicsNodes - 1) * subdiv + 1;
|
||||
if (needed > _rCapacity)
|
||||
{
|
||||
// 理论上不该发生(_rCapacity 用 maxNodes & idle 分配)
|
||||
// 保险扩容一次
|
||||
_rCapacity = needed;
|
||||
_rPoints = new Vector3[_rCapacity];
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
int last = _physicsNodes - 1;
|
||||
|
||||
for (int seg = 0; seg < last; seg++)
|
||||
{
|
||||
int i0 = seg - 1;
|
||||
if (i0 < 0) i0 = 0;
|
||||
int i1 = seg;
|
||||
int i2 = seg + 1;
|
||||
int i3 = seg + 2;
|
||||
if (i3 > last) i3 = last;
|
||||
|
||||
Vector3 p0 = _pCurr[i0];
|
||||
Vector3 p1 = _pCurr[i1];
|
||||
Vector3 p2 = _pCurr[i2];
|
||||
Vector3 p3 = _pCurr[i3];
|
||||
|
||||
for (int s = 0; s < subdiv; s++)
|
||||
{
|
||||
float t = tc.t[s];
|
||||
float t2 = tc.t2[s];
|
||||
float t3 = tc.t3[s];
|
||||
|
||||
// inline CatmullRom(少一次函数调用)
|
||||
Vector3 cr =
|
||||
0.5f * (
|
||||
(2f * p1) +
|
||||
(-p0 + p2) * t +
|
||||
(2f * p0 - 5f * p1 + 4f * p2 - p3) * t2 +
|
||||
(-p0 + 3f * p1 - 3f * p2 + p3) * t3
|
||||
);
|
||||
|
||||
// Linear Y
|
||||
cr.y = p1.y + (p2.y - p1.y) * t;
|
||||
|
||||
_rPoints[idx++] = cr;
|
||||
}
|
||||
}
|
||||
|
||||
_rPoints[idx++] = _pCurr[last];
|
||||
|
||||
_lineRenderer.positionCount = idx;
|
||||
_lineRenderer.SetPositions(_rPoints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ✅ 用 sqrMagnitude 比较阈值,避免 sqrt
|
||||
/// </summary>
|
||||
private int PickRenderSubdivisions_Fast()
|
||||
{
|
||||
int idle = Mathf.Max(1, renderSubdivisionsIdle);
|
||||
int moving = Mathf.Max(1, renderSubdivisionsMoving);
|
||||
|
||||
float thr = movingSpeedThreshold;
|
||||
float thrSq = (thr * _dt) * (thr * _dt); // 因为我们用 disp = curr-prev(单位是米/step),所以阈值要乘 dt
|
||||
|
||||
float sumSq = 0f;
|
||||
int count = Mathf.Max(1, _physicsNodes - 2);
|
||||
|
||||
for (int i = 1; i < _physicsNodes - 1; i++)
|
||||
{
|
||||
Vector3 disp = _pCurr[i] - _pPrev[i];
|
||||
sumSq += disp.sqrMagnitude;
|
||||
}
|
||||
|
||||
float avgSq = sumSq / count;
|
||||
|
||||
return (avgSq > thrSq) ? moving : idle;
|
||||
}
|
||||
|
||||
private static void BuildTCaches(int subdiv, ref TCaches caches)
|
||||
{
|
||||
subdiv = Mathf.Max(1, subdiv);
|
||||
caches.t = new float[subdiv];
|
||||
caches.t2 = new float[subdiv];
|
||||
caches.t3 = new float[subdiv];
|
||||
|
||||
float inv = 1f / subdiv;
|
||||
for (int s = 0; s < subdiv; s++)
|
||||
{
|
||||
float t = s * inv;
|
||||
float t2 = t * t;
|
||||
caches.t[s] = t;
|
||||
caches.t2[s] = t2;
|
||||
caches.t3[s] = t2 * t;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (_pCurr == null) return;
|
||||
Gizmos.color = Color.yellow;
|
||||
for (int i = 0; i < _physicsNodes; i++)
|
||||
Gizmos.DrawSphere(_pCurr[i], 0.01f);
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Rope/Rope.cs.meta
Normal file
3
Assets/Scripts/Fishing/Rope/Rope.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98ba9d435a0e49c9bb527c34cc91894d
|
||||
timeCreated: 1766759607
|
||||
3
Assets/Scripts/Fishing/Tackle.meta
Normal file
3
Assets/Scripts/Fishing/Tackle.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 139e43e2a118492c974b67decf15056d
|
||||
timeCreated: 1766477309
|
||||
14
Assets/Scripts/Fishing/Tackle/FBait.cs
Normal file
14
Assets/Scripts/Fishing/Tackle/FBait.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FBait.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FBait.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed7126c6f37c427e88ba321c63aeac2f
|
||||
timeCreated: 1766582532
|
||||
14
Assets/Scripts/Fishing/Tackle/FBobber.cs
Normal file
14
Assets/Scripts/Fishing/Tackle/FBobber.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FBobber : FGearBase
|
||||
{
|
||||
protected override void OnInit()
|
||||
{
|
||||
// transform.position = Rod.lineHandler.LineConnector_1.transform.position;
|
||||
SetParent(Rod.Line.Bobber.transform);
|
||||
transform.localPosition = Vector3.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FBobber.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FBobber.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89060cfcd521410caf2f00ae7ecfa135
|
||||
timeCreated: 1766477995
|
||||
9
Assets/Scripts/Fishing/Tackle/FFish.cs
Normal file
9
Assets/Scripts/Fishing/Tackle/FFish.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FFish : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FFish.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FFish.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d76aeec1876a4df2a93e8e8dcaee30fa
|
||||
timeCreated: 1766586324
|
||||
36
Assets/Scripts/Fishing/Tackle/FGearBase.cs
Normal file
36
Assets/Scripts/Fishing/Tackle/FGearBase.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Fantasy;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public abstract class FGearBase : MonoBehaviour
|
||||
{
|
||||
public FPlayer Player { get; protected set; }
|
||||
public FRod Rod { get; protected set; }
|
||||
public ItemInfo ItemInfo;
|
||||
|
||||
|
||||
public virtual void Init(FPlayer player, FRod rod)
|
||||
{
|
||||
Player = player;
|
||||
Rod = rod;
|
||||
OnInit();
|
||||
}
|
||||
|
||||
public void SetItemInfo(ItemInfo itemInfo)
|
||||
{
|
||||
ItemInfo = itemInfo;
|
||||
}
|
||||
|
||||
|
||||
protected void SetParent(Transform parent)
|
||||
{
|
||||
transform.SetParent(parent);
|
||||
transform.localPosition = Vector3.zero;
|
||||
transform.localEulerAngles = Vector3.zero;
|
||||
transform.localScale = Vector3.one;
|
||||
}
|
||||
|
||||
protected abstract void OnInit();
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FGearBase.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FGearBase.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 708753789f5b41f48b9b18197f54a9df
|
||||
timeCreated: 1766582740
|
||||
9
Assets/Scripts/Fishing/Tackle/FHandItem.cs
Normal file
9
Assets/Scripts/Fishing/Tackle/FHandItem.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FHandItem : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FHandItem.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FHandItem.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5460b0f542fd45e38145b2a4fb12e329
|
||||
timeCreated: 1766583615
|
||||
30
Assets/Scripts/Fishing/Tackle/FHook.cs
Normal file
30
Assets/Scripts/Fishing/Tackle/FHook.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FHook : FGearBase
|
||||
{
|
||||
public HookAsset hookAsset;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
hookAsset = GetComponent<HookAsset>();
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
|
||||
// transform.position = Rod.lineHandler.LineConnector_2.transform.position;
|
||||
// transform.rotation = Rod.lineHandler.LineConnector_2.transform.rotation; // 确保旋转也同步
|
||||
// SetParent(Rod.lineHandler.LineConnector_2.transform);
|
||||
|
||||
|
||||
SetParent(Rod.Line.Lure.transform);
|
||||
transform.localPosition = Vector3.zero;
|
||||
|
||||
// var target = lineHandler.LineConnector_2.GetComponent<Rigidbody>();
|
||||
// var joint = Hook.gameObject.GetComponent<ConfigurableJoint>();
|
||||
// joint.connectedBody = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FHook.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FHook.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b4736177aeb4b70ba352e385554e5ab
|
||||
timeCreated: 1766477615
|
||||
127
Assets/Scripts/Fishing/Tackle/FLine.cs
Normal file
127
Assets/Scripts/Fishing/Tackle/FLine.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NBC;
|
||||
// using Obi;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FLine : FGearBase
|
||||
{
|
||||
// [SerializeField] private ObiParticleAttachment startParticleAttachment;
|
||||
[SerializeField] private bool isLureConnect;
|
||||
[SerializeField] private RodLine rodLine;
|
||||
[SerializeField] private Rope fishingRope;
|
||||
[SerializeField] private Rope bobberRope;
|
||||
public LureController Lure;
|
||||
public BobberController Bobber;
|
||||
|
||||
|
||||
private float _groundSetting = 0.5f;
|
||||
|
||||
private float _LineOnSpool = 100f;
|
||||
|
||||
private float _LineThickness = 0.0007f;
|
||||
|
||||
public bool IsLure => isLureConnect;
|
||||
|
||||
// public event Action OnLinePulled;
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
var tipRb = Rod.Asset.LineConnectorRigidbody;
|
||||
if (isLureConnect)
|
||||
{
|
||||
Lure.SetJoint(tipRb);
|
||||
Lure.EnableCollision(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
fishingRope.startAnchor = tipRb;
|
||||
Bobber.SetJoint(tipRb);
|
||||
Lure.SetJoint(Bobber.rbody);
|
||||
Lure.gameObject.SetActive(true);
|
||||
Lure.EnableCollision(false);
|
||||
Lure.SetKinematic(false);
|
||||
}
|
||||
|
||||
GetComponentsInChildren<Transform>(includeInactive: true).ToList().ForEach(delegate(Transform i)
|
||||
{
|
||||
i.gameObject.SetActive(true);
|
||||
});
|
||||
|
||||
StartCoroutine(LureUseGravity());
|
||||
if (isLureConnect)
|
||||
{
|
||||
fishingRope.Init(Rod);
|
||||
}
|
||||
else
|
||||
{
|
||||
fishingRope.Init(Rod);
|
||||
bobberRope.Init(Rod);
|
||||
}
|
||||
|
||||
// rodLine.GenerateLineRendererRope(guides.ToArray(), _LineThickness);
|
||||
}
|
||||
|
||||
public void InitTest(Rigidbody tipRb)
|
||||
{
|
||||
if (isLureConnect)
|
||||
{
|
||||
Lure.SetJoint(tipRb);
|
||||
Lure.EnableCollision(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
fishingRope.startAnchor = tipRb;
|
||||
Bobber.SetJoint(tipRb);
|
||||
Lure.SetJoint(Bobber.rbody);
|
||||
Lure.gameObject.SetActive(true);
|
||||
Lure.EnableCollision(false);
|
||||
Lure.SetKinematic(false);
|
||||
}
|
||||
|
||||
GetComponentsInChildren<Transform>(includeInactive: true).ToList().ForEach(delegate(Transform i)
|
||||
{
|
||||
i.gameObject.SetActive(true);
|
||||
});
|
||||
|
||||
StartCoroutine(LureUseGravity());
|
||||
if (isLureConnect)
|
||||
{
|
||||
fishingRope.Init(Rod);
|
||||
}
|
||||
else
|
||||
{
|
||||
fishingRope.Init(Rod);
|
||||
bobberRope.Init(Rod);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator LureUseGravity()
|
||||
{
|
||||
yield return 1;
|
||||
Lure.gameObject.SetActive(false);
|
||||
Lure.gameObject.SetActive(true);
|
||||
yield return 1;
|
||||
Lure.RBody.useGravity = true;
|
||||
}
|
||||
|
||||
|
||||
public void EnableLineRenderers()
|
||||
{
|
||||
// foreach (ObiRopeExtrudedRenderer item in GetComponentsInChildren<ObiRopeExtrudedRenderer>().ToList())
|
||||
// {
|
||||
// item.enabled = true;
|
||||
// }
|
||||
}
|
||||
|
||||
public void SetObiRopeStretch(float value)
|
||||
{
|
||||
Log.Error($"SetObiRopeStretch={value}");
|
||||
fishingRope.SetTargetLength(value - 0.2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FLine.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FLine.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0403ffd74ce46fab8bd4ef057e51432
|
||||
timeCreated: 1766582567
|
||||
194
Assets/Scripts/Fishing/Tackle/FLineHandler.cs
Normal file
194
Assets/Scripts/Fishing/Tackle/FLineHandler.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
// using NBF;
|
||||
// using Obi;
|
||||
// using UnityEngine;
|
||||
//
|
||||
// public class FLineHandler : MonoBehaviour
|
||||
// {
|
||||
// public enum LineType
|
||||
// {
|
||||
// None = 0,
|
||||
// OneSegment = 1,
|
||||
// TwoSegment = 2,
|
||||
// ThereSegment = 3
|
||||
// }
|
||||
//
|
||||
// public LineType lineType = LineType.TwoSegment;
|
||||
//
|
||||
// // public ObiParticleAttachment startParticleAttachment;
|
||||
//
|
||||
// public ObiRope obiRopeSegment_1;
|
||||
//
|
||||
// public ObiRope obiRopeSegment_2;
|
||||
//
|
||||
// public ObiRope obiRopeSegment_3;
|
||||
//
|
||||
// public FixedLine LineConnector_0;
|
||||
//
|
||||
// public SpringJoint LineConnector_1;
|
||||
//
|
||||
// public SpringJoint LineConnector_2;
|
||||
//
|
||||
// public SpringJoint LineConnector_3;
|
||||
//
|
||||
// // [HideInInspector] public FFishingLine currentRodFishingLineComponent;
|
||||
//
|
||||
// // public ObiParticleAttachment toRodConnector;
|
||||
//
|
||||
// // public float PhisicsLineOut { get; set; }
|
||||
//
|
||||
// public float ObiLineOut;
|
||||
//
|
||||
// [HideInInspector] public Rigidbody EndLineRigidbody_0;
|
||||
//
|
||||
// [HideInInspector] public Rigidbody EndLineRigidbody_1;
|
||||
//
|
||||
// [HideInInspector] public Rigidbody EndLineRigidbody_2;
|
||||
//
|
||||
// [HideInInspector] public Rigidbody EndLineRigidbody_3;
|
||||
//
|
||||
// // public JointPinchController pinchController;
|
||||
//
|
||||
// public FRod Rod;
|
||||
//
|
||||
// private Transform waterPlane;
|
||||
//
|
||||
//
|
||||
// public LineRenderer LineRenderer1;
|
||||
// public LineRenderer LineRenderer2;
|
||||
//
|
||||
// // public float ropeToHookDistance;
|
||||
//
|
||||
// void Start()
|
||||
// {
|
||||
// ObiLineOut = obiRopeSegment_1.stretchingScale;
|
||||
// if ((bool)LineConnector_0)
|
||||
// {
|
||||
// EndLineRigidbody_0 = LineConnector_0.GetComponent<Rigidbody>();
|
||||
// }
|
||||
//
|
||||
// if ((bool)LineConnector_1)
|
||||
// {
|
||||
// EndLineRigidbody_1 = LineConnector_1.GetComponent<Rigidbody>();
|
||||
// }
|
||||
//
|
||||
// if ((bool)LineConnector_2)
|
||||
// {
|
||||
// EndLineRigidbody_2 = LineConnector_2.GetComponent<Rigidbody>();
|
||||
// // var fixedJoint = LineConnector_2.GetComponent<FixedJoint>();
|
||||
// // pinchController = LineConnector_2.gameObject.AddComponent<JointPinchController>();
|
||||
// }
|
||||
//
|
||||
// if ((bool)LineConnector_3)
|
||||
// {
|
||||
// EndLineRigidbody_3 = LineConnector_3.GetComponent<Rigidbody>();
|
||||
// }
|
||||
//
|
||||
// waterPlane = GameObject.FindGameObjectWithTag("Water").transform;
|
||||
//
|
||||
// Debug.LogError($"rope.restLength={obiRopeSegment_1.restLength} LineConnector_1={LineConnector_1.maxDistance}");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// void Update()
|
||||
// {
|
||||
// if (!Rod) return;
|
||||
//
|
||||
//
|
||||
// // ropeToHookDistance = Vector3.Distance(toRodConnector.transform.position, LineConnector_1.transform.position);
|
||||
//
|
||||
// ObiLineOut = 0.1f + Rod.lineLength;
|
||||
// float target = (0f - Mathf.Clamp(Rod.linelenghtDiferent, -1f, 0f)) * 0.1f;
|
||||
// if (Rod.linelenghtDiferent >= 0f)
|
||||
// {
|
||||
// obiRopeSegment_1.stretchCompliance = Mathf.MoveTowards(obiRopeSegment_1.stretchCompliance, target,
|
||||
// Time.smoothDeltaTime * (1f * Rod.linelenghtDiferent));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// obiRopeSegment_1.stretchCompliance = Mathf.MoveTowards(obiRopeSegment_1.stretchCompliance, target,
|
||||
// Time.smoothDeltaTime * 0.1f);
|
||||
// }
|
||||
//
|
||||
// if (Rod.lineLength == 0f)
|
||||
// {
|
||||
// obiRopeSegment_1.stretchCompliance = 0f;
|
||||
// }
|
||||
//
|
||||
// if ((bool)obiRopeSegment_2)
|
||||
// {
|
||||
// if (!Rod.currentFish)
|
||||
// {
|
||||
// obiRopeSegment_2.stretchCompliance = obiRopeSegment_2.stretchingScale * 0.004f;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// obiRopeSegment_2.stretchCompliance = 0f;
|
||||
// }
|
||||
//
|
||||
// //TODO:TEST
|
||||
// obiRopeSegment_2.stretchingScale = 0.13F;
|
||||
// }
|
||||
//
|
||||
// obiRopeSegment_1.stretchingScale = ObiLineOut;
|
||||
// obiRopeSegment_1.stretchingScale = 1;
|
||||
// LineConnector_1.maxDistance = 0.1f + Rod.lineLength;
|
||||
// if (Input.GetKey(KeyCode.E))
|
||||
// {
|
||||
// // var speed = 1;
|
||||
// // obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// // Debug.Log(obiRopeSegment_1.restLength);
|
||||
// }
|
||||
//
|
||||
// // var addLength = LineConnector_1.maxDistance - obiRopeSegment_1.restLength;
|
||||
// // if (Mathf.Abs(addLength) > 0.001f)
|
||||
// // {
|
||||
// // obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// // }
|
||||
//
|
||||
// // if (!Mathf.Approximately(LineConnector_1.maxDistance, obiRopeSegment_1.restLength))
|
||||
// // {
|
||||
// // obiRopeCursor_1.ChangeLength(LineConnector_1.maxDistance);
|
||||
// // }
|
||||
//
|
||||
// // obiRopeCursor_1.pos
|
||||
//
|
||||
//
|
||||
// // LineConnector_1.minDistance = LineConnector_1.maxDistance;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public void SetSegmentTwoLenght(float lenght)
|
||||
// {
|
||||
// LineConnector_2.maxDistance = lenght;
|
||||
// // obiRopeCursor_2.ChangeLength(lenght);
|
||||
// // LineConnector_2.minDistance = LineConnector_2.maxDistance;
|
||||
// }
|
||||
//
|
||||
// private void FixedUpdate()
|
||||
// {
|
||||
// // BindRod();
|
||||
// LineWaterDisplacement();
|
||||
// }
|
||||
//
|
||||
// private void BindRod()
|
||||
// {
|
||||
// if (!Rod || !Rod.Asset) return;
|
||||
// LineConnector_0.transform.position = Rod.Asset.lineConnector.position;
|
||||
// }
|
||||
//
|
||||
// private void LineWaterDisplacement()
|
||||
// {
|
||||
// if (!waterPlane)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// for (int i = 0; i < obiRopeSegment_1.activeParticleCount; i++)
|
||||
// {
|
||||
// if (obiRopeSegment_1.GetParticlePosition(i).y < waterPlane.position.y)
|
||||
// {
|
||||
// // obiRopeSegment_1.AddForceParticle(i, Vector3.up * 10f, ForceMode.Acceleration);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
3
Assets/Scripts/Fishing/Tackle/FLineHandler.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FLineHandler.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 331fde19f47e431092cf5bd57c7bcfe4
|
||||
timeCreated: 1766586159
|
||||
21
Assets/Scripts/Fishing/Tackle/FLure.cs
Normal file
21
Assets/Scripts/Fishing/Tackle/FLure.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FLure : FGearBase
|
||||
{
|
||||
protected override void OnInit()
|
||||
{
|
||||
// transform.position = Rod.lineHandler.LineConnector_1.transform.position;
|
||||
|
||||
// Lure.gameObject.GetComponent<ConfigurableJoint>().connectedBody =
|
||||
// lineHandler.LineConnector_1.GetComponent<Rigidbody>();
|
||||
// LureHookWaterDisplacement = Lure.GetComponent<FWaterDisplacement>();
|
||||
|
||||
// SetParent(Rod.lineHandler.LineConnector_1.transform);
|
||||
|
||||
SetParent(Rod.Line.Lure.transform);
|
||||
transform.localPosition = Vector3.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FLure.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FLure.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f91ba5f4ca745d4b29fb2116781e25f
|
||||
timeCreated: 1766478011
|
||||
32
Assets/Scripts/Fishing/Tackle/FReel.cs
Normal file
32
Assets/Scripts/Fishing/Tackle/FReel.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Collections;
|
||||
using Fantasy;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FReel : FGearBase
|
||||
{
|
||||
public bool isBlockLineByFinger { get; set; }
|
||||
|
||||
|
||||
[SerializeField] public float reelingDrag = 1f;
|
||||
|
||||
public ReelAsset Asset;
|
||||
public ReelAnimator AnimatorCtrl;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Asset = GetComponent<ReelAsset>();
|
||||
AnimatorCtrl = Asset.animator.gameObject.GetComponent<ReelAnimator>();
|
||||
if (AnimatorCtrl == null)
|
||||
{
|
||||
AnimatorCtrl = Asset.animator.gameObject.AddComponent<ReelAnimator>();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FReel.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FReel.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b48fc45344c5439c9d19897cb5987abf
|
||||
timeCreated: 1766478030
|
||||
350
Assets/Scripts/Fishing/Tackle/FRod.cs
Normal file
350
Assets/Scripts/Fishing/Tackle/FRod.cs
Normal file
@@ -0,0 +1,350 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using NBC.Asset;
|
||||
using NBF.Utils;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FRod : FHandItem
|
||||
{
|
||||
private float _tension;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 可用的
|
||||
/// </summary>
|
||||
public bool Usable { get; private set; }
|
||||
|
||||
public RodAsset Asset;
|
||||
|
||||
public FPlayer Player { get; protected set; }
|
||||
public ItemInfo ItemInfo;
|
||||
|
||||
public FReel Reel;
|
||||
public FHook Hook;
|
||||
public FBobber Bobber;
|
||||
public FBait Bait;
|
||||
public FLure Lure;
|
||||
public FWeight Weight;
|
||||
public FLine Line;
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// 鱼线处理器
|
||||
// /// </summary>
|
||||
// public FLineHandler lineHandler;
|
||||
|
||||
public Transform GearRoot;
|
||||
|
||||
// public FWaterDisplacement LureHookWaterDisplacement;
|
||||
|
||||
[HideInInspector] public FFish currentFish;
|
||||
public RodRingNode[] rings;
|
||||
|
||||
/// <summary>
|
||||
/// 线长度
|
||||
/// </summary>
|
||||
public float lineLength = 1.5f;
|
||||
|
||||
/// <summary>
|
||||
/// 浮漂线长度
|
||||
/// </summary>
|
||||
public float floatLength = 0.5f;
|
||||
|
||||
public float Tension
|
||||
{
|
||||
get => _tension;
|
||||
private set
|
||||
{
|
||||
if (!Mathf.Approximately(_tension, value))
|
||||
{
|
||||
_tension = value;
|
||||
// OnTensionChanged?.Invoke(_tension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float currentLineTension;
|
||||
public float linelenghtDiferent;
|
||||
public float currentLineStrenght;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Asset = GetComponent<RodAsset>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Alpha0))
|
||||
{
|
||||
SetLineLength(lineLength);
|
||||
}
|
||||
else if (Input.GetKeyDown(KeyCode.Plus) || Input.GetKeyDown(KeyCode.Equals))
|
||||
{
|
||||
lineLength += 0.1f;
|
||||
SetLineLength(lineLength);
|
||||
}
|
||||
else if (Input.GetKeyDown(KeyCode.Minus))
|
||||
{
|
||||
lineLength -= 0.1f;
|
||||
SetLineLength(lineLength);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLineLength(float lineLength, bool stretchRope = true)
|
||||
{
|
||||
if (!Line) return;
|
||||
if (Line.IsLure)
|
||||
{
|
||||
//没有浮漂类型
|
||||
Line.Lure.SetJointDistance(lineLength);
|
||||
if (stretchRope)
|
||||
{
|
||||
Line.SetObiRopeStretch(Tension > 0f ? 0f : lineLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//有浮漂
|
||||
Line.Lure.SetJointDistance(floatLength);
|
||||
Line.Bobber.SetJointDistance(lineLength - floatLength);
|
||||
if (stretchRope)
|
||||
{
|
||||
Line.SetObiRopeStretch(Tension > 0f ? 0f : lineLength - floatLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
Test();
|
||||
}
|
||||
|
||||
public IEnumerator Destroy()
|
||||
{
|
||||
if (GearRoot != null)
|
||||
{
|
||||
Object.Destroy(GearRoot.gameObject);
|
||||
}
|
||||
|
||||
yield return 1;
|
||||
}
|
||||
|
||||
public IEnumerator InitRod(FPlayer player, ItemInfo itemInfo)
|
||||
{
|
||||
ItemInfo = itemInfo;
|
||||
Player = player;
|
||||
|
||||
transform.localPosition = Vector3.zero;
|
||||
transform.localRotation = Quaternion.identity;
|
||||
transform.localScale = Vector3.one;
|
||||
SceneSettings.Instance.GearNode.position = Player.transform.position;
|
||||
yield return 1;
|
||||
var obj = new GameObject($"rod_{itemInfo.Id}_{itemInfo.ConfigId}");
|
||||
obj.transform.SetParent(SceneSettings.Instance.GearNode);
|
||||
// obj.transform.SetParent(player.transform);
|
||||
// obj.transform.localPosition = Vector3.zero;
|
||||
obj.transform.position = player.transform.position;
|
||||
obj.transform.rotation = player.transform.rotation;
|
||||
obj.transform.localScale = Vector3.one;
|
||||
GearRoot = obj.transform;
|
||||
|
||||
var parent = GearRoot;
|
||||
|
||||
List<ItemInfo> children = RoleModel.Instance.GetBindItems(itemInfo.Id);
|
||||
|
||||
ItemInfo lineItemInfo = null;
|
||||
|
||||
CreateFishingHandler();
|
||||
yield return 1; //等待1帧
|
||||
// children.Sort();
|
||||
foreach (var child in children)
|
||||
{
|
||||
var itemType = child.ConfigId.GetItemType();
|
||||
if (itemType == ItemType.Reel)
|
||||
{
|
||||
Reel = child.Config.InstantiateAndComponent<FReel>(Asset.ReelConnector, Vector3.zero,
|
||||
Quaternion.identity);
|
||||
Reel.SetItemInfo(child);
|
||||
}
|
||||
else if (itemType == ItemType.Bobber)
|
||||
{
|
||||
Bobber = child.Config.InstantiateAndComponent<FBobber>(parent, Vector3.zero,
|
||||
Quaternion.identity);
|
||||
Bobber.SetItemInfo(child);
|
||||
}
|
||||
else if (itemType == ItemType.Hook)
|
||||
{
|
||||
Hook = child.Config.InstantiateAndComponent<FHook>(parent, Vector3.zero,
|
||||
Quaternion.identity);
|
||||
Hook.SetItemInfo(child);
|
||||
}
|
||||
else if (itemType == ItemType.Bait)
|
||||
{
|
||||
Bait = child.Config.InstantiateAndComponent<FBait>(parent, Vector3.zero,
|
||||
Quaternion.identity);
|
||||
Bait.SetItemInfo(child);
|
||||
}
|
||||
else if (itemType == ItemType.Lure)
|
||||
{
|
||||
Lure = child.Config.InstantiateAndComponent<FLure>(parent, Vector3.zero,
|
||||
Quaternion.identity);
|
||||
Lure.SetItemInfo(child);
|
||||
}
|
||||
else if (itemType == ItemType.Weight)
|
||||
{
|
||||
Weight = child.Config.InstantiateAndComponent<FWeight>(parent, Vector3.zero,
|
||||
Quaternion.identity);
|
||||
Weight.SetItemInfo(child);
|
||||
}
|
||||
else if (itemType == ItemType.Line)
|
||||
{
|
||||
lineItemInfo = child;
|
||||
}
|
||||
}
|
||||
|
||||
yield return 1;
|
||||
if (Reel)
|
||||
{
|
||||
Reel.reelingDrag = 0.699f;
|
||||
Reel.transform.SetParent(Asset.ReelConnector);
|
||||
Reel.transform.localPosition = Vector3.zero;
|
||||
Reel.transform.localEulerAngles = Vector3.zero;
|
||||
Reel.Init(player, this);
|
||||
}
|
||||
|
||||
if (Bobber)
|
||||
{
|
||||
Bobber.Init(Player, this);
|
||||
}
|
||||
|
||||
if (Hook)
|
||||
{
|
||||
Hook.Init(Player, this);
|
||||
// LureHookWaterDisplacement = Hook.GetComponent<FWaterDisplacement>();
|
||||
}
|
||||
|
||||
if (Bait)
|
||||
{
|
||||
Bait.Init(Player, this);
|
||||
}
|
||||
|
||||
if (Lure)
|
||||
{
|
||||
Lure.Init(Player, this);
|
||||
}
|
||||
|
||||
if (Weight)
|
||||
{
|
||||
Weight.Init(Player, this);
|
||||
}
|
||||
|
||||
yield return 1; //等待1帧
|
||||
|
||||
transform.SetParent(Player.ModelAsset.RodRoot);
|
||||
transform.localPosition = Vector3.zero;
|
||||
transform.rotation = Player.ModelAsset.RodRoot.rotation;
|
||||
|
||||
Usable = true;
|
||||
}
|
||||
|
||||
|
||||
public void CreateFishingHandler()
|
||||
{
|
||||
if (Line == null)
|
||||
{
|
||||
Debug.LogError("创建钓组=====");
|
||||
var rodType = (ItemSubType)ItemInfo.Config.Type;
|
||||
if (rodType == ItemSubType.RodTele)
|
||||
{
|
||||
CreateObiFishingLine(0);
|
||||
}
|
||||
else if (rodType == ItemSubType.RodSpine || rodType == ItemSubType.RodBolo)
|
||||
{
|
||||
CreateObiFishingLine(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void CreateObiFishingLine(int currentLineTypeIndex)
|
||||
{
|
||||
if (!Line)
|
||||
{
|
||||
var lineSolverPrefab = Assets.Load<GameObject>("Assets/ResRaw/Prefabs/Line/LineSolver.prefab");
|
||||
var solver = Instantiate(lineSolverPrefab, GearRoot);
|
||||
solver.transform.position = Asset.lineConnector.position;
|
||||
solver.transform.rotation = Asset.lineConnector.rotation;
|
||||
var indexNames = new[] { "fishing line float set", "fishing line spinning" };
|
||||
var path =
|
||||
$"Assets/ResRaw/Prefabs/Line/{indexNames[currentLineTypeIndex]}.prefab";
|
||||
var prefab = Assets.Load<GameObject>(path);
|
||||
|
||||
GameObject obj = Instantiate(prefab, solver.transform);
|
||||
obj.transform.localPosition = Vector3.zero;
|
||||
obj.transform.localScale = Vector3.one;
|
||||
obj.transform.rotation = Quaternion.identity;
|
||||
|
||||
Line = obj.GetComponent<FLine>();
|
||||
Line.transform.position = Asset.lineConnector.position;
|
||||
Line.Init(this.Player, this);
|
||||
|
||||
// var obiSolver = solver.GetComponent<ObiSolver>();
|
||||
// obiSolver.parameters.ambientWind = Vector3.zero;
|
||||
// obiSolver.wind.
|
||||
// obiSolver.simulateWhenInvisible
|
||||
}
|
||||
}
|
||||
|
||||
public void SetRing(RodRingAsset ringAsset)
|
||||
{
|
||||
if (Asset.rings == null || Asset.rings.Length < 1) return;
|
||||
|
||||
var trans = ringAsset.rings;
|
||||
RodRingNode lastRingNode = null;
|
||||
List<RodRingNode> list = new List<RodRingNode>();
|
||||
for (int i = 0; i < Asset.rings.Length; i++)
|
||||
{
|
||||
var ring = Asset.rings[i];
|
||||
if (ring == null)
|
||||
{
|
||||
Log.Error($"ring is null,index={i}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var lastName = ring.name.GetLastString();
|
||||
foreach (var tran in trans)
|
||||
{
|
||||
var ringNode = tran.ring;
|
||||
var lastName2 = ringNode.name.GetLastString();
|
||||
if (lastName != lastName2) continue;
|
||||
list.Add(tran);
|
||||
ringNode.SetParent(ring);
|
||||
ringNode.localPosition = Vector3.zero;
|
||||
ringNode.localRotation = Quaternion.identity;
|
||||
lastRingNode = tran;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastRingNode != null)
|
||||
{
|
||||
Asset.lineConnector = lastRingNode.point;
|
||||
}
|
||||
|
||||
rings = list.ToArray();
|
||||
}
|
||||
|
||||
private void Test()
|
||||
{
|
||||
// var root = Player.ModelAsset.RodRoot;
|
||||
// if (!root) return;
|
||||
// transform.SetPositionAndRotation(root.position, root.rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FRod.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FRod.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef4dfd89c0c34916be91b55490eb1c9f
|
||||
timeCreated: 1766477316
|
||||
233
Assets/Scripts/Fishing/Tackle/FVirtualTackle.cs
Normal file
233
Assets/Scripts/Fishing/Tackle/FVirtualTackle.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
// using System.Collections;
|
||||
// using Fantasy;
|
||||
// using UnityEngine;
|
||||
//
|
||||
// namespace NBF
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// 虚拟钓组
|
||||
// /// </summary>
|
||||
// public class FVirtualTackle
|
||||
// {
|
||||
// private ItemInfo _itemInfo;
|
||||
// private FPlayer _player;
|
||||
//
|
||||
//
|
||||
// public FRod Rod;
|
||||
//
|
||||
//
|
||||
// public FVirtualTackle(ItemInfo itemInfo, FPlayer player)
|
||||
// {
|
||||
// _itemInfo = itemInfo;
|
||||
// _player = player;
|
||||
// }
|
||||
//
|
||||
// public IEnumerator Create()
|
||||
// {
|
||||
// var parent = _player.transform;
|
||||
// // parent.position = _player.transform.position;
|
||||
//
|
||||
//
|
||||
// Rod = _itemInfo.Config.InstantiateAndComponent<FRod>(parent, Vector3.zero, Quaternion.identity);
|
||||
//
|
||||
//
|
||||
// // var rodObject = _itemInfo.Config.Instantiate(parent, Vector3.zero, Quaternion.identity);
|
||||
// // Rod = rodObject.GetComponent<FRod>();
|
||||
// // if (Rod == null)
|
||||
// // {
|
||||
// // Rod = rodObject.AddComponent<FRod>();
|
||||
// // }
|
||||
// // var rodConfig = RodConfig.Get(itemInfo.ConfigId);
|
||||
// // itemInfo.Config
|
||||
//
|
||||
// // var data = Player.Data.currentGear;
|
||||
// // var rodConfig = data.rod.Config;
|
||||
// // var cloneObj = rodConfig.Instantiate(parent, Vector3.zero, Player.MainArm.RodContainer.rotation);
|
||||
// // if (cloneObj == null)
|
||||
// // {
|
||||
// // yield break;
|
||||
// // }
|
||||
// //
|
||||
// // Rod = cloneObj.GetComponent<FRod>();
|
||||
// // if (Rod == null)
|
||||
// // {
|
||||
// // Rod = cloneObj.AddComponent<FRod>();
|
||||
// // }
|
||||
// //
|
||||
// //
|
||||
// // if (Rod)
|
||||
// // {
|
||||
// // Rod.transform.localPosition = Vector3.zero;
|
||||
// // Rod.transform.rotation = Player.MainArm.RodContainer.rotation;
|
||||
// //
|
||||
// // if (rodConfig.ring > 0)
|
||||
// // {
|
||||
// // var ringConfig = GameRings.Get(rodConfig.ring);
|
||||
// // var ringObject = ringConfig.Instantiate(Rod.transform);
|
||||
// // ringObject.SetActive(false);
|
||||
// // Rod.SetRing(ringObject.GetComponent<RodRingAsset>());
|
||||
// // }
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // yield break;
|
||||
// // }
|
||||
// //
|
||||
// // if (data.line != null)
|
||||
// // {
|
||||
// // var linePrefab = data.line.Config.Instantiate(parent);
|
||||
// // Line = linePrefab.GetComponent<FLine>();
|
||||
// // }
|
||||
// //
|
||||
// // if (data.reel != null)
|
||||
// // {
|
||||
// // var reelPrefab = data.reel.Config.Create(parent);
|
||||
// // Reel = reelPrefab.GetComponent<FReel>();
|
||||
// // }
|
||||
// //
|
||||
// // if (data.bobber != null)
|
||||
// // {
|
||||
// // var bobberPrefab = data.bobber.Config.Create(parent);
|
||||
// // Bobber = bobberPrefab.GetComponent<FFloat>();
|
||||
// // }
|
||||
// //
|
||||
// // if (data.hook != null)
|
||||
// // {
|
||||
// // var hookPrefab = data.hook.Config.Create(parent);
|
||||
// // Hook = hookPrefab.GetComponent<FHook>();
|
||||
// // }
|
||||
// //
|
||||
// // if (data.bait != null)
|
||||
// // {
|
||||
// // var baitPrefab = data.bait.Config.Create(parent);
|
||||
// //
|
||||
// // if (baitPrefab.TryGetComponent<FBait>(out var bait))
|
||||
// // {
|
||||
// // Bait = bait;
|
||||
// // }
|
||||
// // }
|
||||
// //
|
||||
// // if (data.lure != null)
|
||||
// // {
|
||||
// // var baitPrefab = data.lure.Config.Create(parent);
|
||||
// // if (baitPrefab.TryGetComponent<FLure>(out var lure))
|
||||
// // {
|
||||
// // Lure = lure;
|
||||
// // }
|
||||
// // }
|
||||
// //
|
||||
// //
|
||||
// // if (data.weight != null)
|
||||
// // {
|
||||
// // var weightPrefab = data.weight.Config.Instantiate(parent);
|
||||
// // Weight = weightPrefab.GetComponent<FWeight>();
|
||||
// // }
|
||||
// //
|
||||
// // Debug.LogError("CreateOrHideGear");
|
||||
// // yield return 1;
|
||||
// // Rod.Initialize(Player, data.rod);
|
||||
// // Rod.CreateFishingHandler();
|
||||
// //
|
||||
// // if (Line)
|
||||
// // {
|
||||
// // Line.Initialize(Player, data.line);
|
||||
// //
|
||||
// //
|
||||
// // if ((bool)Rod.lineHandler.obiRopeSegment_1)
|
||||
// // {
|
||||
// // Rod.lineHandler.obiRopeSegment_1.GetComponent<MeshRenderer>().material =
|
||||
// // Line.lineMat;
|
||||
// // }
|
||||
// //
|
||||
// // if ((bool)Rod.lineHandler.obiRopeSegment_2)
|
||||
// // {
|
||||
// // Rod.lineHandler.obiRopeSegment_2.GetComponent<MeshRenderer>().material =
|
||||
// // Line.lineMat;
|
||||
// // }
|
||||
// //
|
||||
// // if ((bool)Rod.lineHandler.obiRopeSegment_3)
|
||||
// // {
|
||||
// // Rod.lineHandler.obiRopeSegment_3.GetComponent<MeshRenderer>().material =
|
||||
// // Line.lineMat;
|
||||
// // }
|
||||
// // }
|
||||
// //
|
||||
// // if (Reel)
|
||||
// // {
|
||||
// // // Reel.maxReelStrength = data.reel.Config.strength;
|
||||
// // // Reel.reelingSpeed = 0.5f; //slotsEquip.reel.currentSpeed;
|
||||
// // Reel.reelingDrag = 0.699f; //slotsEquip.reel.currentDrag;
|
||||
// // Reel.transform.SetParent(Rod.rodAsset.ReelConnector);
|
||||
// // Reel.transform.localPosition = Vector3.zero;
|
||||
// // Reel.transform.localEulerAngles = Vector3.zero;
|
||||
// // // Reel.reelAsset.szpulaObject.GetComponent<MeshRenderer>().material = Line.szpulaMat;
|
||||
// // Reel.Initialize(Player, data.reel);
|
||||
// // }
|
||||
// //
|
||||
// // if (Bobber)
|
||||
// // {
|
||||
// // Bobber.floatDisplacement = data.bobber.Config.displacement;
|
||||
// // // if ((double)slotsEquip.ffloat.lastSetGroundValue > 0.2)
|
||||
// // // {
|
||||
// // // Bobber.newDeepth = slotsEquip.ffloat.lastSetGroundValue;
|
||||
// // // }
|
||||
// //
|
||||
// // Bobber.newDeepth = 0.5f;
|
||||
// //
|
||||
// // Bobber.Initialize(Player, data.bobber);
|
||||
// // Bobber.transform.position = Rod.lineHandler.LineConnector_1.transform.position;
|
||||
// // Bobber.gameObject.GetComponent<ConfigurableJoint>().connectedBody =
|
||||
// // Rod.lineHandler.LineConnector_1.GetComponent<Rigidbody>();
|
||||
// // }
|
||||
// //
|
||||
// //
|
||||
// // if (Hook)
|
||||
// // {
|
||||
// // Hook.Initialize(Player, data.hook);
|
||||
// //
|
||||
// // Hook.transform.position = Rod.lineHandler.LineConnector_2.transform.position;
|
||||
// // Hook.transform.rotation = Rod.lineHandler.LineConnector_2.transform.rotation; // 确保旋转也同步
|
||||
// // var target = Rod.lineHandler.LineConnector_2.GetComponent<Rigidbody>();
|
||||
// // var joint = Hook.gameObject.GetComponent<ConfigurableJoint>();
|
||||
// // // // 关键设置:关闭自动锚点计算,手动设置锚点
|
||||
// // // joint.autoConfigureConnectedAnchor = false;
|
||||
// // // joint.anchor = Vector3.zero; // 以 Hook 自身中心为锚点
|
||||
// // // joint.connectedAnchor = Vector3.zero; // 以目标物体的中心为锚点
|
||||
// // joint.connectedBody = target;
|
||||
// // // // 强制物理引擎立即更新变换(避免1帧延迟)
|
||||
// // // Physics.SyncTransforms();
|
||||
// // // joint.autoConfigureConnectedAnchor = false;
|
||||
// // // joint.anchor = Vector3.zero;
|
||||
// // // joint.connectedAnchor = Vector3.zero;
|
||||
// // Rod.LureHookWaterDisplacement = Hook.GetComponent<FWaterDisplacement>();
|
||||
// // }
|
||||
// //
|
||||
// // if (Bait)
|
||||
// // {
|
||||
// // Bait.Initialize(Player, data.bait);
|
||||
// // Bait.transform.position = Hook.hookAsset.baitConnector.position;
|
||||
// // Bait.transform.SetParent(Hook.hookAsset.baitConnector);
|
||||
// // }
|
||||
// //
|
||||
// // if (Lure)
|
||||
// // {
|
||||
// // Lure.Initialize(Player, data.bait);
|
||||
// // Lure.transform.position = Rod.lineHandler.LineConnector_1.transform.position;
|
||||
// // Lure.gameObject.GetComponent<ConfigurableJoint>().connectedBody =
|
||||
// // Rod.lineHandler.LineConnector_1.GetComponent<Rigidbody>();
|
||||
// // Rod.LureHookWaterDisplacement = Lure.GetComponent<FWaterDisplacement>();
|
||||
// // }
|
||||
// //
|
||||
// // if (Weight)
|
||||
// // {
|
||||
// // Weight.weight = data.weight.Config.weight;
|
||||
// // Weight.Initialize(Player, data.weight);
|
||||
// // }
|
||||
// }
|
||||
//
|
||||
// public IEnumerator Destroy()
|
||||
// {
|
||||
// yield return 1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
3
Assets/Scripts/Fishing/Tackle/FVirtualTackle.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FVirtualTackle.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4092f341d83540c0b6ba0e2db3669f1b
|
||||
timeCreated: 1766478162
|
||||
12
Assets/Scripts/Fishing/Tackle/FWeight.cs
Normal file
12
Assets/Scripts/Fishing/Tackle/FWeight.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class FWeight : FGearBase
|
||||
{
|
||||
protected override void OnInit()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Fishing/Tackle/FWeight.cs.meta
Normal file
3
Assets/Scripts/Fishing/Tackle/FWeight.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a68c58e07092402dbc37a5f287e70b9b
|
||||
timeCreated: 1766582543
|
||||
Reference in New Issue
Block a user