1、承君此诺,必守一生。好了,我们正式开始技术分享(博主内心有很多话想说)!在仙剑奇侠传四中,玩家可以通过鼠标右键来旋转场景(水平方向),按下前进键时角色将向着朝前(Forward)的方向运动,按下后退键时角色将向着朝后(Backword)的方向运动、当按下向左、向右键时角色将向左、向右旋转 90度。从严格意义上来说,仙剑四不算是一部完全的 3D游戏,因为游戏视角是锁死的,所以玩家在平时跑地图的时候基本上是看不到角色的正面的。我们今天要做的就是基于 Unity3D来做这样一个角色控制器。虽然 Unity3D为我们提供了第一人称角色控制器和第三人称角色控制器,但是博主感觉官方提供的第三人称角色控制器
2、用起来感觉怪怪的,尤其是按下左右键时那个旋转,感觉控制起来很不容易,所以博主决定自己来写一个角色控制器。首先我们打开项目,我们还是用昨天的那个例子:很多朋友可能觉得控制角色的脚本很好写嘛,这是一个我们通常见到的版本:1./向左 2.if(Input.GetKey(KeyCode.A)3.4.SetAnimation(LeftAnim);5.this.mState=PersonState.Walk;6.mHero.transform.Translate(Vector3.right*Time.deltaTime*mSpeed);7.8./向右 9.if(Input.GetKey(KeyCode.D
3、)10.11.SetAnimation(RightAnim);12.this.mState=PersonState.Walk;13.mHero.transform.Translate(Vector3.right*Time.deltaTime*(-mSpeed);14.15./向上 16.if(Input.GetKey(KeyCode.W)17.18.SetAnimation(UpAnim);19.this.mState=PersonState.Walk;20.mHero.transform.Translate(Vector3.forward*Time.deltaTime*(-mSpeed);2
4、1.22./向下 23.if(Input.GetKey(KeyCode.S)24.25.SetAnimation(DownAnim);26.this.mState=PersonState.Walk;27.mHero.transform.Translate(Vector3.forward*Time.deltaTime*(mSpeed);28.Vector3 mHeroPos=mHero.transform.position;29.复制代码 那么,我们姑且认为这样写没什么问题,那么现在我们导入官方提供的 Script脚本资源包,找到 MouseLook 脚本,在 Update()方法中添加对右键是
5、否按下的判断,这样我们就可以实现按下鼠标右键时视角的旋转。修改后的脚本如下:1.2.using UnityEngine;3.using System.Collections;4.5./MouseLook rotates the transform based on the mouse delta.6./Minimum and Maximum values can be used to constrain the possible rotation 7.8./To make an FPS style character:9./-Create a capsule.10./-Add the Mous
6、eLook script to the capsule.11./-Set the mouse look to use LookX.(You want to only turn character but not tilt it)12./-Add FPSInputController script to the capsule 13./-A CharacterMotor and a CharacterController component will be automatically added.14.15./-Create a camera.Make the camera a child of
7、 the capsule.Reset its transform.16./-Add a MouseLook script to the camera.17./-Set the mouse look to use LookY.(You want the camera to tilt up and down like a head.The character already turns.)18.AddComponentMenu(Camera-Control/Mouse Look)19.public class MouseLook:MonoBehaviour 20.21.public enum Ro
8、tationAxes MouseXAndY=0,MouseX=1,MouseY=2 22.public RotationAxes axes=RotationAxes.MouseXAndY;23.public float sensitivityX=15F;24.public float sensitivityY=15F;25.26.public float minimumX=-360F;27.public float maximumX=360F;28.29.public float minimumY=-60F;30.public float maximumY=60F;31.32.float ro
9、tationY=0F;33.34.void Update()35.36.if(Input.GetMouseButton(1)37.38.if(axes=RotationAxes.MouseXAndY)39.40.float rotationX=transform.localEulerAngles.y+Input.GetAxis(Mouse X)*sensitivityX;41.42.rotationY+=Input.GetAxis(Mouse Y)*sensitivityY;43.rotationY=Mathf.Clamp(rotationY,minimumY,maximumY);44.45.
10、transform.localEulerAngles=new Vector3(-rotationY,rotationX,0);46.47.else if(axes=RotationAxes.MouseX)48.49.transform.Rotate(0,Input.GetAxis(Mouse X)*sensitivityX,0);50.51.52.else 53.54.rotationY+=Input.GetAxis(Mouse Y)*sensitivityY;55.rotationY=Mathf.Clamp(rotationY,minimumY,maximumY);56.57.transfo
11、rm.localEulerAngles=new Vector3(-rotationY,transform.localEulerAngles.y,0);58.59.60.61.62.void Start()63.64./Make the rigid body not change rotation 65.if(rigidbody)66.rigidbody.freezeRotation=true;67.68.69.复制代码 接下来,我们将这个脚本拖放到我们的角色上,运行游戏,我们发现了一个问题:当旋转视角后,角色并没有如我们期望地向朝前的方向移动,相反,角色依然沿着世界坐标系里的 Vector3.
12、forward 向前运动。按照我们的想法,当旋转视角以后,角色应该可以朝着前方运动。怎么办呢?这里我们在上面的代码中加上这样的代码:1.2./计算旋转角 3.if(Input.GetMouseButton(1)4.5./计算水平旋转角 6.mAngles+=Input.GetAxis(Mouse X)*15;7./旋转角色 8.transform.rotation=Quaternion.Euler(new Vector3(0,mAngles,0);9.10.复制代码 这里代码的作用是当用户按下鼠标右键旋转视角时,我们首先计算在水平上的旋转角,然后让角色的坐标系跟着视角一起旋转,这样就相当于把
13、Vector3.forward 和旋转后的目标角度平行。这样的话,我们控制人物向前运动的时候,它就会按照这个新的方向去运动。这样我们的第一个问题就解决了。我们继续往下看,由于这个模型中只提供了一个行走/奔跑的方向动画,所以就出现了角色动画和角色行为不符的问题,怎么办呢?这时候,我们可以这样想,我们可以先把角色旋转到指定的方向,然后让角色朝着向前的方向运动,这样角色动画和角色行为就可以相互对应起来了。为此我们做下面的工作:1./角色行动方向枚举 2.public enum PersonDirection 3.4./正常向前 5.Forward=90,6./正常向后 7.Backward=270,
14、8./正常向左 9.Left=180,10./正常向右 11.Right=0,12.复制代码 我们这里定义了四个方向上的角度,当我们角色旋转到 Forward 方向时,我们根据用户按下的键,来判断角色要向那个方向旋转:1.private void SetPersonDirection(PersonDirection mDir)2.3./根据目标方向与当前方向让角色旋转 4.if(mDirection!=mDir)5.6.transform.Rotate(Vector3.up*(mDirection-mDir);7.mDirection=mDir;8.9.复制代码 在该方法中,如果目标方向大于当
15、前方向,那么角色将逆时针旋转,否则将顺时针旋转,角度差值为 0,则不旋转。好了,现在角色已经旋转到相应的方向了,我们让它朝前运动:1.transform.Translate(Vector3.forward*WalkSpeed*Time.deltaTime);复制代码 接下来我们为角色定义状态枚举值:1./角色状态枚举 2.public enum PersonState 3.4.idle,5.run,6.walk,7.jump,8.attack 9.复制代码 我们在上面的代码上面做修改,最终形成的代码为:4.5.public class RPGControl:MonoBehaviour 6.7.
16、/定义角色动画 8.private Animation mAnimation;9./定义角色状态 10.public PersonState mState=PersonState.idle;11./定义方向状态 12.public PersonDirection mDirection=PersonDirection.Forward;13./定义角色弹跳量 14.public float mJumpValue=2F;15./定义旋转角 16.private float mAngles;17./定义相机 18.public GameObject mCamera;19./定义角色行动方式 20.pu
17、blic PersonState RunOrWalk=PersonState.walk;21.22.public float WalkSpeed=1.5F;23.public float RunSpeed=3.0F;24./角色状态枚举 25.public enum PersonState 26.27.idle,28.run,29.walk,30.jump,31.attack 32.33./角色行动方向枚举 34.public enum PersonDirection 35.36./正常向前 37.Forward=90,38./正常向后 39.Backward=270,40./正常向左 41.
18、Left=180,42./正常向右 43.Right=0,44.45.46.void Start()47.48./获取动画 49.mAnimation=gameObject.GetComponent();50.51.52.void Update()53.54./前进 55.if(Input.GetKey(KeyCode.W)56.57.SetPersonDirection(PersonDirection.Forward);58.SetPersonAnimation();59.60./后退 61.if(Input.GetKey(KeyCode.S)62.63.SetPersonDirection
19、(PersonDirection.Backward);64.SetPersonAnimation();65.66./向左 67.if(Input.GetKey(KeyCode.A)68.69.SetPersonDirection(PersonDirection.Left);70.SetPersonAnimation();71.72./向右 73.if(Input.GetKey(KeyCode.D)74.75.SetPersonDirection(PersonDirection.Right);76.SetPersonAnimation();77.78./巡逻或等待 79.if(Input.Get
20、KeyUp(KeyCode.A)|Input.GetKeyUp(KeyCode.D)|Input.GetKeyUp(KeyCode.S)|Input.GetKeyUp(KeyCode.W)|Input.GetKeyUp(KeyCode.Space)80.81.mAnimation.Play(idle);82.mState=PersonState.idle;83.84./跳跃 85.if(Input.GetKey(KeyCode.Space)86.87.transform.GetComponent().AddForce(Vector3.up*mJumpValue,ForceMode.Force)
21、;88.mAnimation.Play(Jump);89.mState=PersonState.jump;90.91./攻击 92.if(Input.GetMouseButton(0)93.94.mAnimation.Play(Attack);95.mState=PersonState.attack;96.StartCoroutine(ReSetState);97.98./计算旋转角 99.if(Input.GetMouseButton(1)100.101./计算水平旋转角 102.mAngles+=Input.GetAxis(Mouse X)*15;103./旋转角色 104.transfo
22、rm.rotation=Quaternion.Euler(new Vector3(0,mAngles,0);105.106.107.108.private void SetPersonDirection(PersonDirection mDir)109.110./根据目标方向与当前方向让角色旋转 111.if(mDirection!=mDir)112.113.transform.Rotate(Vector3.up*(mDirection-mDir);114.mDirection=mDir;115.116.117.118.private void SetPersonAnimation()119.
23、120.if(RunOrWalk=PersonState.walk)121.122.mAnimation.Play(Walk);123.mState=PersonState.walk;124.transform.Translate(Vector3.forward*WalkSpeed*Time.deltaTime);125.126.else if(RunOrWalk=PersonState.run)127.128.mAnimation.Play(Run);129.mState=PersonState.run;130.transform.Translate(Vector3.forward*RunS
24、peed*Time.deltaTime);131.132.133.134.IEnumerator ReSetState()135.136./当攻击动画播放完毕时,自动切换到巡逻状态 137.yield return new WaitForSeconds(mAnimation.clip.length);138.mAnimation.Play(idle);139.mState=PersonState.idle;140.141.142.143.复制代码 其中,SetPersonAnimation()方法将根据 RunOrWalk 值来决定角色是采用行走还是奔跑的方式移动。最后,我们加上一个摄像机跟随的脚本 SmoothFollow,这个脚本在官方提供的 Script 资源包里,我们把该脚本绑定到主摄像机上,并设定我们的角色为其跟随目标。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1