From f9a9f26009500413a174382b23799be5e0379c83 Mon Sep 17 00:00:00 2001 From: "Bob.Song" <605277374@qq.com> Date: Wed, 3 Sep 2025 20:08:42 +0800 Subject: [PATCH] map --- Assets/Scripts/Fishing2/Helper/MapHelper.cs | 2 +- Assets/Scripts/Fishing2/Helper/UnitHelper.cs | 2 + Assets/Scripts/Fishing2/Map/Map.cs | 9 +- Assets/Scripts/Fishing2/Move/MoveComponent.cs | 279 +++++++++++++++++- Assets/Scripts/Fishing2/Move/MoveEvent.cs | 17 ++ .../Scripts/Fishing2/Move/MoveEvent.cs.meta | 3 + Assets/Scripts/Fishing2/Unit/MapUnit.cs | 23 +- Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs | 38 +++ .../Fishing2/Unit/MapUnitBasic.cs.meta | 3 + 9 files changed, 356 insertions(+), 20 deletions(-) create mode 100644 Assets/Scripts/Fishing2/Move/MoveEvent.cs create mode 100644 Assets/Scripts/Fishing2/Move/MoveEvent.cs.meta create mode 100644 Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs create mode 100644 Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs.meta diff --git a/Assets/Scripts/Fishing2/Helper/MapHelper.cs b/Assets/Scripts/Fishing2/Helper/MapHelper.cs index b90619e43..0adb4735b 100644 --- a/Assets/Scripts/Fishing2/Helper/MapHelper.cs +++ b/Assets/Scripts/Fishing2/Helper/MapHelper.cs @@ -85,7 +85,7 @@ namespace NBF.Fishing2 public static async FTask LoadMap(this Map self) { var sceneName = "Map99"; - self.CreteSelfMapUnit(); + self.CreteMapUnit(); //加载场景== await SceneHelper.LoadScene(sceneName); await self.LoadAllUnit(); diff --git a/Assets/Scripts/Fishing2/Helper/UnitHelper.cs b/Assets/Scripts/Fishing2/Helper/UnitHelper.cs index ce6f55f2a..00233ad4a 100644 --- a/Assets/Scripts/Fishing2/Helper/UnitHelper.cs +++ b/Assets/Scripts/Fishing2/Helper/UnitHelper.cs @@ -1,4 +1,5 @@ using NBC; +using NBC.Entitas; namespace NBF.Fishing2 { @@ -8,5 +9,6 @@ namespace NBF.Fishing2 { await FTask.CompletedTask; } + } } \ No newline at end of file diff --git a/Assets/Scripts/Fishing2/Map/Map.cs b/Assets/Scripts/Fishing2/Map/Map.cs index 12961f23f..87d59dd8d 100644 --- a/Assets/Scripts/Fishing2/Map/Map.cs +++ b/Assets/Scripts/Fishing2/Map/Map.cs @@ -19,24 +19,25 @@ namespace NBF.Fishing2 /// public Dictionary Units = new Dictionary(); - - /// /// 创建地图单位 /// - /// - public void CreteSelfMapUnit() + public void CreteMapUnit() { //创建自己 var role = Scene.GetComponent(); var mapUnitInfo = role.GetMapUnitInfo(); CreteMapUnit(mapUnitInfo); + + //创建其他玩家 } + public void CreteMapUnit(MapUnitInfo unitInfo) { var mapUnit = Entity.Create(Scene, unitInfo.RoleInfo.RoleId, true, true); + mapUnit.SetUnitInfo(unitInfo); Add(mapUnit); } diff --git a/Assets/Scripts/Fishing2/Move/MoveComponent.cs b/Assets/Scripts/Fishing2/Move/MoveComponent.cs index b0167f789..0adb67143 100644 --- a/Assets/Scripts/Fishing2/Move/MoveComponent.cs +++ b/Assets/Scripts/Fishing2/Move/MoveComponent.cs @@ -1,6 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using NBC; using NBC.Entitas; +using NBC.Entitas.Interface; +using NBC.Helper; using Unity.Mathematics; namespace NBF.Fishing2 @@ -59,4 +62,278 @@ namespace NBF.Fishing2 public quaternion From; public quaternion To; } + + public static class MoveComponentSystem + { + public class MoveComponentDestroySystem : DestroySystem + { + protected override void Destroy(MoveComponent self) + { + } + } + + + public static bool IsArrived(this MoveComponent self) + { + return self.Targets.Count == 0; + } + + public static bool ChangeSpeed(this MoveComponent self, float speed) + { + if (self.IsArrived()) + { + return false; + } + + if (speed < 0.0001) + { + return false; + } + + MapUnit unit = self.GetParent(); + List path = new List(); + + self.MoveForward(false); + path.Add(unit.Position); // 第一个是Unit的pos + for (int i = self.N; i < self.Targets.Count; ++i) + { + path.Add(self.Targets[i]); + } + + self.MoveToAsync(path, speed).Coroutine(); + return true; + } + + // 该方法不需要用cancelToken的方式取消,因为即使不传入cancelToken,多次调用该方法也要取消之前的移动协程,上层可以stop取消 + public static async FTask MoveToAsync(this MoveComponent self, List target, float speed, + int turnTime = 100) + { + self.Stop(false); + foreach (float3 v in target) + { + self.Targets.Add(v); + } + + self.IsTurnHorizontal = true; + self.TurnTime = turnTime; + self.Speed = speed; + self.tcs = FTask.Create(true); + + self.Scene.EventComponent.Publish(new MoveStart() { Unit = self.GetParent() }); + + self.StartMove(); + + bool moveRet = await self.tcs; + + if (moveRet) + { + self.Scene.EventComponent.Publish(new MoveStop() { Unit = self.GetParent() }); + } + + return moveRet; + } + + // ret: 停止的时候,移动协程的返回值 + private static void MoveForward(this MoveComponent self, bool ret) + { + MapUnit unit = self.GetParent(); + + long timeNow = TimeHelper.Now; + long moveTime = timeNow - self.StartTime; + + while (true) + { + if (moveTime <= 0) + { + return; + } + + // 计算位置插值 + if (moveTime >= self.NeedTime) + { + unit.Position = self.NextTarget; + if (self.TurnTime > 0) + { + unit.Rotation = self.To; + } + } + else + { + // 计算位置插值 + float amount = moveTime * 1f / self.NeedTime; + if (amount > 0) + { + float3 newPos = math.lerp(self.StartPos, self.NextTarget, amount); + unit.Position = newPos; + } + + // 计算方向插值 + if (self.TurnTime > 0) + { + amount = moveTime * 1f / self.TurnTime; + if (amount > 1) + { + amount = 1f; + } + + quaternion q = math.slerp(self.From, self.To, amount); + unit.Rotation = q; + } + } + + moveTime -= self.NeedTime; + + // 表示这个点还没走完,等下一帧再来 + if (moveTime < 0) + { + return; + } + + // 到这里说明这个点已经走完 + + // 如果是最后一个点 + if (self.N >= self.Targets.Count - 1) + { + unit.Position = self.NextTarget; + unit.Rotation = self.To; + + self.MoveFinish(ret); + return; + } + + self.SetNextTarget(); + } + } + + private static void StartMove(this MoveComponent self) + { + self.BeginTime = TimeHelper.Now; + self.StartTime = self.BeginTime; + self.SetNextTarget(); + + // self.Scene.TimerComponent.Net.RepeatedTimer() + + self.MoveTimer = self.Scene.TimerComponent.Net.RepeatedTimer(1000 * 60, () => + { + try + { + self.MoveForward(true); + } + catch (Exception e) + { + Log.Error($"move timer error: {self.Id}\n{e}"); + } + }); + } + + private static void SetNextTarget(this MoveComponent self) + { + MapUnit unit = self.GetParent(); + + ++self.N; + + // 时间计算用服务端的位置, 但是移动要用客户端的位置来插值 + float3 v = self.GetFaceV(); + float distance = math.length(v); + + // 插值的起始点要以unit的真实位置来算 + self.StartPos = unit.Position; + + self.StartTime += self.NeedTime; + + self.NeedTime = (long)(distance / self.Speed * 1000); + + if (self.TurnTime > 0) + { + // 要用unit的位置 + float3 faceV = self.GetFaceV(); + if (math.lengthsq(faceV) < 0.0001f) + { + return; + } + + self.From = unit.Rotation; + + if (self.IsTurnHorizontal) + { + faceV.y = 0; + } + + if (Math.Abs(faceV.x) > 0.01 || Math.Abs(faceV.z) > 0.01) + { + self.To = quaternion.LookRotation(faceV, math.up()); + } + + return; + } + + if (self.TurnTime == 0) // turn time == 0 立即转向 + { + float3 faceV = self.GetFaceV(); + if (self.IsTurnHorizontal) + { + faceV.y = 0; + } + + if (Math.Abs(faceV.x) > 0.01 || Math.Abs(faceV.z) > 0.01) + { + self.To = quaternion.LookRotation(faceV, math.up()); + unit.Rotation = self.To; + } + } + } + + private static float3 GetFaceV(this MoveComponent self) + { + return self.NextTarget - self.PreTarget; + } + + public static bool FlashTo(this MoveComponent self, float3 target) + { + MapUnit unit = self.GetParent(); + unit.Position = target; + return true; + } + + // ret: 停止的时候,移动协程的返回值 + public static void Stop(this MoveComponent self, bool ret) + { + if (self.Targets.Count > 0) + { + self.MoveForward(ret); + } + + self.MoveFinish(ret); + if (!ret) + { + self.Scene.EventComponent.Publish( new MoveStop() { Unit = self.GetParent() }); + } + } + + private static void MoveFinish(this MoveComponent self, bool ret) + { + if (self.StartTime == 0) + { + return; + } + + self.StartTime = 0; + self.StartPos = float3.zero; + self.BeginTime = 0; + self.NeedTime = 0; + self.Targets.Clear(); + self.Speed = 0; + self.N = 0; + self.TurnTime = 0; + self.IsTurnHorizontal = false; + self.Scene.TimerComponent.Net.Remove(self.MoveTimer); + + if (self.tcs != null) + { + var tcs = self.tcs; + self.tcs = null; + tcs.SetResult(ret); + } + } + } } \ No newline at end of file diff --git a/Assets/Scripts/Fishing2/Move/MoveEvent.cs b/Assets/Scripts/Fishing2/Move/MoveEvent.cs new file mode 100644 index 000000000..402869eca --- /dev/null +++ b/Assets/Scripts/Fishing2/Move/MoveEvent.cs @@ -0,0 +1,17 @@ +namespace NBF.Fishing2 +{ + public struct MoveStart + { + public MapUnit Unit; + } + + public struct MoveStop + { + public MapUnit Unit; + } + + public struct MoveTimer + { + + } +} \ No newline at end of file diff --git a/Assets/Scripts/Fishing2/Move/MoveEvent.cs.meta b/Assets/Scripts/Fishing2/Move/MoveEvent.cs.meta new file mode 100644 index 000000000..1cc6f3831 --- /dev/null +++ b/Assets/Scripts/Fishing2/Move/MoveEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2b438b0d299c4b7186d21faf5de07cca +timeCreated: 1756882697 \ No newline at end of file diff --git a/Assets/Scripts/Fishing2/Unit/MapUnit.cs b/Assets/Scripts/Fishing2/Unit/MapUnit.cs index 730b53029..9ac0473a8 100644 --- a/Assets/Scripts/Fishing2/Unit/MapUnit.cs +++ b/Assets/Scripts/Fishing2/Unit/MapUnit.cs @@ -1,4 +1,5 @@ -using NBC; + +using NBC; using NBC.Entitas; using Unity.Mathematics; @@ -51,21 +52,15 @@ namespace NBF.Fishing2 } - #region 静态 - - public static MapUnit Create(Map map, MapUnitInfo unitInfo, bool isMainPlayer = false) - { - var unit = Entity.Create(map.Scene, true, true); - unit.SetUnitInfo(unitInfo); - return null; - } - - #endregion - - public void SetUnitInfo(MapUnitInfo unitInfo) { - NumericComponent numericComponent = AddComponent(); + var moveComponent = GetOrAddComponent(); + GetOrAddComponent(); + var unitBasic = GetOrAddComponent(); + unitBasic.UpdateInfo(unitInfo); + + + var numericComponent = GetOrAddComponent(); foreach (var kv in unitInfo.KV) { numericComponent.Set(kv.Key, kv.Value); diff --git a/Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs b/Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs new file mode 100644 index 000000000..a79a6ec38 --- /dev/null +++ b/Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs @@ -0,0 +1,38 @@ +using NBC; +using NBC.Entitas; + +namespace NBF.Fishing2 +{ + public class MapUnitBasic : Entity + { + /// + /// 昵称 + /// + public string NickName; + + /// + /// 头像 + /// + public string Head; + + /// + /// 国家 + /// + public string Country; + + /// + /// 等级 + /// + public int Level; + + + + public void UpdateInfo(MapUnitInfo mapUnitInfo) + { + NickName = mapUnitInfo.RoleInfo.NickName; + Head = mapUnitInfo.RoleInfo.Head; + Country = mapUnitInfo.RoleInfo.Country; + Level = mapUnitInfo.RoleInfo.Level; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs.meta b/Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs.meta new file mode 100644 index 000000000..b2751b348 --- /dev/null +++ b/Assets/Scripts/Fishing2/Unit/MapUnitBasic.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fac7cf28f53b4a929d2584c9a95fd242 +timeCreated: 1756881253 \ No newline at end of file