|  |  |  | using Entitas; | 
					
						
							|  |  |  | using UnityEngine; | 
					
						
							|  |  |  | using Game; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public class MoveSystem : IExecuteSystem, IInitializeSystem | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     private IGroup<GameEntity> _entities; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public void Initialize() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         _entities = Util.GetGroup(GameMatcher.Move); | 
					
						
							|  |  |  |         EventManager.Instance.AddEvent<PEntityMoveInput>(EEvent.EntityMoveInput, OnEntityMove); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public void Execute() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         //TODO 现在物理系统用unity原生的 | 
					
						
							|  |  |  |         foreach (var entity in _entities) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             CheckHit(entity); //打射线 检查角色四周是否有阻挡 是否在地面 | 
					
						
							|  |  |  |             TurnUpdate(entity.move); //更新转向 | 
					
						
							|  |  |  |             ReboundWallUpdate(entity); //更新撞墙反弹 | 
					
						
							|  |  |  |             ReboundUpdate(entity); //更新落地反弹 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static void OnEntityMove(PEntityMoveInput param) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var entity = Util.GetEntity(param.EntityID); | 
					
						
							|  |  |  |         var move = entity.move; | 
					
						
							|  |  |  |         switch ((int)param.CommandType) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             case (int)EMoveCommandType.Stop: | 
					
						
							|  |  |  |                 move.IsWalk = false; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case (int)EMoveCommandType.FunctionKey: | 
					
						
							|  |  |  |                 HandleFunctionCommand(move, param.Command); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case (int)EMoveCommandType.Move: | 
					
						
							|  |  |  |                 HandleMoveCommand(move, param.Command); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static void HandleFunctionCommand(MoveComponent move, EMoveCommand command) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (command) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             case EMoveCommand.Jump: | 
					
						
							|  |  |  |                 move.IsJumpPressed = true; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case EMoveCommand.JumpRelease: | 
					
						
							|  |  |  |                 move.IsJumpPressed = false; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static void HandleMoveCommand(MoveComponent move, EMoveCommand command) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         move.IsWalk = true; | 
					
						
							|  |  |  |         if (GameConst.MoveCommand2Dir.TryGetValue(command, out var moveDir)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             move.MoveDir = moveDir; | 
					
						
							|  |  |  |             if (moveDir == GameConst.Stop) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 move.IsWalk = false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch ((int)command) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             case (int)EMoveCommand.Stop: | 
					
						
							|  |  |  |             case (int)EMoveCommand.Up: | 
					
						
							|  |  |  |             case (int)EMoveCommand.Down: | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 if (move.IsFreeTurn) | 
					
						
							|  |  |  |                     move.IsRight = move.MoveDir.x > 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static void TurnUpdate(MoveComponent move) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!move.MoveParam.NeedScale) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         move.TransformViewMain.localScale = new Vector3((move.IsRight ? 1f : -1f), 1, 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static void ReboundUpdate(GameEntity entity) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var move = entity.move; | 
					
						
							|  |  |  |         if (!move.IsFlowing) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         if (!move.IsGround) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var velocity = move.Velocity; | 
					
						
							|  |  |  |         if (velocity.y > 0) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!entity.hasBuff) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Util.HasSetSpeedBuff(entity.ID())) | 
					
						
							|  |  |  |             return; //强制位移途中不检测 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Util.HasHitDownBuff(entity.ID())) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             //触地反弹 | 
					
						
							|  |  |  |             Util.RemoveHitDownBuff(entity.ID()); | 
					
						
							|  |  |  |             move.Velocity = new Vector3(move.Velocity.x / 2, 6, move.Velocity.z / 2); | 
					
						
							|  |  |  |             move.Position = move.GroundPosition; | 
					
						
							|  |  |  |             if (entity.hasAnimation) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 entity.animation.ReboundMsg = true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             //触地反弹特效 | 
					
						
							|  |  |  |             Util.CastGroundStaticEffect(GameConst.EffectHitGround1, entity.ID()); | 
					
						
							|  |  |  |             //卡帧 | 
					
						
							|  |  |  |             Util.EntityPause(entity, 0.05f); | 
					
						
							|  |  |  |             //抖动 | 
					
						
							|  |  |  |             Util.EntityShake(entity, 2); | 
					
						
							|  |  |  |             //缩放 | 
					
						
							|  |  |  |             Util.EntityScale(entity, Vector3.right * 6); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             //落地 | 
					
						
							|  |  |  |             move.IsFlowing = false; | 
					
						
							|  |  |  |             //触地特效 | 
					
						
							|  |  |  |             Util.CastGroundStaticEffect(GameConst.EffectHitGround2, entity.ID()); | 
					
						
							|  |  |  |             Util.AddStaggerBuff(entity.ID(), 2f); | 
					
						
							|  |  |  |             //缩放 | 
					
						
							|  |  |  |             Util.EntityScale(entity, Vector3.right * 3); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static void ReboundWallUpdate(GameEntity entity) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var move = entity.move; | 
					
						
							|  |  |  |         if (!move.IsFlowing) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         if (!move.IsCrashToWall) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         if (!entity.hasBuff) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Util.HasSetSpeedBuff(entity.ID())) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             //撞墙反弹-大 | 
					
						
							|  |  |  |             Util.RemoveHitDownBuff(entity.ID()); | 
					
						
							|  |  |  |             Util.RemoveSetSpeedBuff(entity.ID()); | 
					
						
							|  |  |  |             //反弹方向xz沿CrashWallNormal,值为当前速度钳制[2,10] | 
					
						
							|  |  |  |             var speed = new Vector3(move.Velocity.x, 0, move.Velocity.z).magnitude; | 
					
						
							|  |  |  |             speed = Mathf.Clamp(speed, 2, 10); | 
					
						
							|  |  |  |             var velocity = move.CrashWallNormal * speed; | 
					
						
							|  |  |  |             move.Velocity = new Vector3(velocity.x, 6, velocity.z); | 
					
						
							|  |  |  |             if (entity.hasAnimation) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 entity.animation.AirHitMsg = true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             //撞墙反弹特效 | 
					
						
							|  |  |  |             Util.CastWallStaticEffect(GameConst.EffectHitWall1, entity.ID(), move.CrashWallPosition, | 
					
						
							|  |  |  |                 move.CrashWallNormal); | 
					
						
							|  |  |  |             //卡帧 | 
					
						
							|  |  |  |             Util.EntityPause(entity, 0.05f); | 
					
						
							|  |  |  |             //抖动 | 
					
						
							|  |  |  |             Util.EntityShake(entity, 2); | 
					
						
							|  |  |  |             //缩放 | 
					
						
							|  |  |  |             Util.EntityScale(entity, Vector3.up * 6); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             //撞墙反弹-小 | 
					
						
							|  |  |  |             var speed = new Vector3(move.Velocity.x, 0, move.Velocity.z).magnitude; | 
					
						
							|  |  |  |             speed = Mathf.Clamp(speed, 2, 3); | 
					
						
							|  |  |  |             var velocity = move.CrashWallNormal * speed; | 
					
						
							|  |  |  |             move.Velocity = velocity; | 
					
						
							|  |  |  |             //撞墙特效 | 
					
						
							|  |  |  |             Util.CastWallStaticEffect(GameConst.EffectHitWall2, entity.ID(), move.CrashWallPosition, | 
					
						
							|  |  |  |                 move.CrashWallNormal); | 
					
						
							|  |  |  |             //缩放 | 
					
						
							|  |  |  |             Util.EntityScale(entity, Vector3.up * 3); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static void CheckHit(GameEntity entity) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         var move = entity.move; | 
					
						
							|  |  |  |         var view = entity.view; | 
					
						
							|  |  |  |         var bodySize = view.Collider.bounds.size; | 
					
						
							|  |  |  |         const float checkOffset = 0.1f; | 
					
						
							|  |  |  |         const float checkLength = 0.2f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //检查落地 | 
					
						
							|  |  |  |         var checkDir = Vector3.down; | 
					
						
							|  |  |  |         var startPos = move.Position + Vector3.up * checkOffset; | 
					
						
							|  |  |  |         move.IsGround = Physics.Raycast(startPos, checkDir, out var hitInfo, checkLength, UtilPhysics.LayerMaskDefault); | 
					
						
							|  |  |  |         move.IsGroundLogic = move.IsGround && move.JumpState == EJumpState.OnGround; | 
					
						
							|  |  |  |         if (move.IsGround) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             move.GroundPosition = hitInfo.point; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Util.Draw(startPos, startPos + checkDir * checkLength, move.IsGround ? Color.red : Color.green); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //检查移动贴墙 | 
					
						
							|  |  |  |         checkDir = move.MoveDir; | 
					
						
							|  |  |  |         startPos = move.Position + Vector3.up * bodySize.y / 2 + checkDir * (bodySize.x / 2 - checkOffset); | 
					
						
							|  |  |  |         move.IsAgainstWall = Physics.Raycast(startPos, checkDir, out hitInfo, checkLength, UtilPhysics.LayerMaskWall); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Util.Draw(startPos, startPos + checkDir * checkLength, move.IsAgainstWall ? Color.red : Color.green); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //检查冲撞贴墙 | 
					
						
							|  |  |  |         checkDir = move.Velocity.normalized; | 
					
						
							|  |  |  |         startPos = move.Position + Vector3.up * bodySize.y / 2 + checkDir * (bodySize.x / 2 - checkOffset); | 
					
						
							|  |  |  |         move.IsCrashToWall = Physics.Raycast(startPos, checkDir, out hitInfo, checkLength, UtilPhysics.LayerMaskWall); | 
					
						
							|  |  |  |         if (move.IsCrashToWall) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             move.CrashWallPosition = hitInfo.point; | 
					
						
							|  |  |  |             move.CrashWallNormal = hitInfo.normal; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Util.Draw(startPos, startPos + checkDir * checkLength, move.IsCrashToWall ? Color.red : Color.green); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |