个人项目(2):摄像机与主角
首先我们实现将摄像机与主体角色绑定,并实现虚拟轴对主体角色的操控及主体角色动画的绑定等。
摄像头跟随
我们首先用ProBuilder工具新建一个Plane,随后将主题角色模型拖入其中,命名位“Player”。随后我们新建一个摄像机脚本,并将其添加到摄像机对象中。
本次项目编写的摄像机脚本较为简单,只能实现单方位的跟随,并不能转动视角,后续可以完善
public class cameramove : MonoBehavIoUr{
public float m_Height = 3f;
public float m_distance = 3f;
public float m_Speed = 3f;
Vector3 m_TargetPosition;
Transform follow;
void Start()
{
follow = GameObject.FindWithTag("Player").transform; //获取游戏主体对象
}
void Update()
{
m_TargetPosition = follow.position + Vector3.up * m_Height - Vector3.forward * m_distance;//计算目标位置
transform.position = Vector3.Lerp (transform.position, m_TargetPosition, m_Speed * Time.deltaTime);//摄像头从当前位置转移到目标位置
transform.LookAt (follow);//镜头看向人物
}
}
虚拟轴控制游戏主体角色以及动画的绑定
horizontal=Input.GetAxis("Horizontal");
vertical=Input.GetAxis("Vertical");
movement.Set(horizontal,0.0f,vertical);
movement.normalize();
if(horizontal!=0f||vertical!=0f){
Rotating(horizontal,vertical);
}
bool hashorizontal=!Mathf.Approximately(horizontal,0.0f);
bool hasvertical=!Mathf.Approximately(vertical,0.0f);
bool moving=hashorizontal||hasvertical;
Animator.SetBool("ismoving",moving);//设置主体角色通过虚拟轴进行运动
horizontal、vertical获取虚拟轴输入,movement设置角色移动方向,moving用于判断角色是否有移动,如果存在移动就会播放人物移动的动画。
Rotating()方法用于实现角色按照角色移动方向的转向,targetRotation为目标旋转。
void Rotating(float horizontal,float vertical){//角色转向
Vector3 target=new Vector3(horizontal,0f,vertical);
Quaternion targetRotation=Quaternion.LookRotation(target,Vector3.up);
Quaternion newRotation=Quaternion.Lerp(Rigidbody.rotation,targetRotation,1);
Rigidbody.MoveRotation(newRotation);
}
OnAnimatorMove()方法可用于处理动画移动以修改根运动的回调,我们可以用该方法实现角色按照动画效果的移动,角色移动主要依靠刚体组件实现。
private void OnAnimatorMove(){//角色运动
Rigidbody.MovePosition(Rigidbody.position+movement*Animator.deltaPosition.magnitude);
}
在动画控制器上我设置了一个ismoving参数,当该参数为真时就会执行运动动画,为假时回到默认动画,不勾选Has Exit Time可以使动画随时暂停,这里的动画资源可以直接从资源包中复制添加。
主体角色动作与动画的绑定
在资源包中我发现该资源拥有盾击、剑劈、冲刺等动作,随后测试中我发现如果把上述动作按照运动动画的方式绑定到角色并用鼠标虚拟轴和键盘空格键控制,只要持续不间断地按下控制键,动画会无限次重复播放,这并不符合常理中按下按键动画会执行直到结束的效果,所以我想到了把这些动作设置成技能并为它们添加冷却时间的设定,当然,相对应的动画控制器也要做些许调整。
制作冷却时间的代码逻辑也比较简单,我们可以用一个布尔类型的参数判断技能能否使用,如果能够使用就执行使用逻辑,如果不能使用则执行冷却逻辑,冷却的话需要设定一个冷却时间以及一个冷却计时器,下面例子中用的是skillCooldownTime1参数是冷却时间,而skillCooldownTimer1是冷却计时器,每当Update()执行时,计时器时间不断增加,当它超过冷却时间后就执行冷却时间结束的逻辑,把计时器时间重新调为0并将判断技能能否使用的布尔值设为真。
这样的计时冷却方法非常实用,后续开发过程中我也多次用到了这种方法,例如人物无敌时间的设置,技能攻击时长的设置等。
if (Input.GetMouseButtonDown(0)&&canUseSkill1)//使用技能1
{
as2.Play();
Animator.Play("Attack01",0,0);
Canvas2.alpha=1;
canUseSkill1=false;
isattack1=true;
invincibility=true;//人物无敌
}
if (canUseSkill1==false)//技能1冷却
{
skillCooldownTimer1+=Time.deltaTime;
Canvas1.alpha=(skillCooldownTime1-skillCooldownTimer1)/skillCooldownTime1;
if (skillCooldownTimer1>=skillCooldownTime1)
{
canUseSkill1=true;
skillCooldownTimer1=0;
Canvas2.alpha=0;
}
}
上面代码中的Canvas1、Canvas2获取的是UI中图片以及文字资源的CanvasGroup组件,该组件可以通过Alpha值改变透明度。具体的实现方法如下所述:
图片方面,我们需要放置两个相同的图片,一个作为底座,颜色设置为白色,另一个用于遮罩,颜色设置为黑色,然后为遮罩用的图片添加CanvasGroup组件,随后我们可以在代码中通过调整遮罩图片的透明度Alpha值来实现技能冷却的实现。文字也是类似,也是需要两组,一组底座一组遮罩,颜色可以自行设置,实现图片相类似的效果就行。添加文字的主要原因是图片显示的不完全,有时候并不能立即判断技能是否已经完成冷却,同时文字也能对技能进行介绍,一举两得。
上述实现方法其实也可以不用CanvasGroup组件,我们可以直接将图片类型设置为Filled,通过代码调整Fill Amount参数来实现同样的效果,在制作人物血条UI上我就使用了这种方法。
与技能图标类似,人物血条同样需要一个底座和遮罩,我这里的底座为白色,遮罩为红色,遮罩图片大小略小于底座图片,遮罩图片组件的相关参数如图:
这样就完成了摄像机跟随、主体人物角色相关动作及其动画的绑定和部分UI的制作。