今天要实现的是一个简单人物控制器。包括用w,a,s,d来控制人物上下左右跑动,鼠标左击发出连招,都是基于老的lagacy的动画。虽然unity3d自带有charactorcontroller,但是并不是很好用,所以人物控制相关的全部自己来实现。先上效果图:
首先下载这个package,里面包含了人物的动作还有地面的模型。将人物和地面都拖进场景中。这里的模型默认的动画模式是lagacy,不用修改。模型有点偏小,改变模型的scale值为10.最好不要改源文件的scale的scale factor,可能会出现骨骼错位的问题。
接下来给摄像机添加一个天空盒组件,添加一个unity自带的天空盒就好。
对于人物还要添加几个component:
添加Rigdbody来控制人物,选择IsKinematic,这样角色就不会被外力影响。加了CapsuleCollider让角色 不掉下去。HeroController用来控制角色的运动和打斗,下面会说。
角色行走
思路很简单,通过wasd获得行走的方向,然后对应控制角色的位移就可以了,不过在变向的时候要注意角色的平滑转身。
首先定义 一个 枚举变量,为角色可能的状态。
public enum ActionState { Attack_1, Attack_2, Attack_3_1, Attack_3_2, Attack_3_3, Attack_4, Fire, Jump, Run, Idle } private ActionState actionState = ActionState.Idle;
void Animate() { float delayTime = -0.1f; switch (actionState) { case ActionState.Attack_3_1: delayTime = -0.1f; playerAnimation.CrossFade("Attack3-1", 0.15f); currentAnimationClip = playerAnimation["Attack3-1"].clip; break; case ActionState.Attack_3_2: delayTime = -0.1f; playerAnimation.CrossFade("Attack3-2", 0.15f); currentAnimationClip = playerAnimation["Attack3-2"].clip; break; case ActionState.Attack_3_3: delayTime = -0.1f; playerAnimation.CrossFade("Attack3-3", 0.15f); currentAnimationClip = playerAnimation["Attack3-3"].clip; break; case ActionState.Attack_4: delayTime = -0.1f; playerAnimation.CrossFade("Attack4", 0.15f); currentAnimationClip = playerAnimation["Attack4"].clip; break; case ActionState.Idle: playerAnimation.CrossFade("Idle", 0.35f); currentAnimationClip = playerAnimation["Idle"].clip; break; case ActionState.Jump: playerAnimation.CrossFade("Jump", 0.15f); currentAnimationClip = playerAnimation["Jump"].clip; break; case ActionState.Run: playerAnimation.CrossFade("Run", 0.15f); currentAnimationClip = playerAnimation["Run"].clip; break; case ActionState.Fire: playerAnimation.CrossFade("Fire", 0.15f); currentAnimationClip = playerAnimation["Fire"].clip; break; default: break; } //Switch to default if an animation is almost over if (playerAnimation[currentAnimationClip.name].time > (playerAnimation[currentAnimationClip.name].length + delayTime)){ actionState = ActionState.Idle; currentAnimationClip = playerAnimation["Idle"].clip; } }
// Update is called once per frame void Update () { float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); MovementManagement (h, v); Animate (); }
MovementManagement函数就是根据输入处理角色行走的
void MovementManagement(float horizontal, float vertical) { if(horizontal != 0f || vertical != 0f) { Rotating(horizontal, vertical); actionState = ActionState.Run; moveDirection = new Vector3(horizontal, 0.0f, vertical); rigidbody.MovePosition(rigidbody.position + speed * moveDirection * Time.deltaTime); } }
void Rotating(float horizontal, float vertival) { Vector3 targetDirection = new Vector3 (horizontal, 0f, vertival); // Create a rotation based on this new vector assuming that up is the global y axis. Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up); // Create a rotation that is an increment closer to the target rotation from the player‘s rotation. Quaternion newRotation = Quaternion.Lerp(rigidbody.rotation, targetRotation, turnSmoothing * Time.deltaTime); // Change the players rotation to this new rotation. rigidbody.MoveRotation(newRotation); }
首先来思考一下逻辑。角色初始值状态是Idle,此时按下攻击,发连招的第一招,如果玩家继续按的话就进入第二招,依次类推,如果中途停下的话,就还是回到Idle状态。这是最简单的单线连招的逻辑,没有考虑打断,多连等情况,代码实现如下:
void AttackLogic() { if (Input.GetButtonDown ("Fire1")) { if(actionState != ActionState.Attack_3_1 && actionState != ActionState.Attack_3_2 && actionState != ActionState.Attack_3_3&& actionState != ActionState.Attack_4) { Debug.Log ("Fire"); actionState = ActionState.Attack_3_1; } else if(actionState == ActionState.Attack_3_1 && playerAnimation[currentAnimationClip.name].time > 1.0f) { actionState = ActionState.Attack_3_2; } else if(actionState == ActionState.Attack_3_2 && playerAnimation[currentAnimationClip.name].time > 1.0f) { actionState = ActionState.Attack_3_3; } else if(actionState == ActionState.Attack_3_3 && playerAnimation[currentAnimationClip.name].time > 1.0f) { actionState = ActionState.Attack_4; } /*else if(actionState == ActionState.Attack_3 && playerAnimation[currentAnimationClip.name].time > 2.0f) { actionState = ActionState.Idle; }*/ } else if(Input.GetButtonDown ("Jump")) { actionState = ActionState.Jump; } else if(Input.GetButtonDown ("Fire2")) { actionState = ActionState.Fire; //if (currentSkill==null) } }
运行一下,就可以实现最开始的那个效果了。
Unity3d toturial - Stealth
Unity3D游戏开发从零单排(六) - 人物运动及攻击连击,布布扣,bubuko.com
Unity3D游戏开发从零单排(六) - 人物运动及攻击连击
原文地址:http://blog.csdn.net/silangquan/article/details/30130683