1、角色体力计算
2、角色疲劳动画
3、体力条制作、跟随
默认做好角色的idle/run/walk动画、切换和玩家输入,我使用的是新输入系统,动画时单变量混合树,参数Sports。
【每一部分功能根据自己需求观看哦】
实现效果
当角色奔跑时,每秒减少1体力
角色走路时,体力不变
角色站立不动,每秒体力加1体力
玩家体力耗尽,不可移动
(1)新建一个脚本挂载到角色身上
//角色速度设置,根据isRunning来判断角色是否奔跑
private Animator animator;
private Vector2 playerInputVec;
private float walkSpeed = 2.0f;
private float runSpeed = 5.0f;
private float currentSpeed;
private float targetSpeed;
private bool isRuning;
//疲劳值设置
private float minTired = 0.0f;
public float MinTired
{
get { return minTired; }
}
private float maxTired = 10.0f;
public float MaxTired
{
get { return maxTired; }
}
private float currentTired;
public float CurrentTired
{
get { return currentTired; }
}
private float TiredIndex;
void Start()
{
animator = GetComponent<Animator>();
}
void FixedUpdate()
{
MovePlayer();
CalculateTired();
}
//移动输入,新输入系统获取玩家输入
public void GetPlayerMoveInput(InputAction.CallbackContext context)
{
playerInputVec = context.ReadValue<Vector2>();//上下左右
}
void MovePlayer()
{
TiredIndex = currentTired >= maxTired ? 0 : 1;
targetSpeed = isRuning ? runSpeed : walkSpeed;
targetSpeed *= playerInputVec.magnitude;//当玩家没按下或没有推动摇杆,目标速度为0
currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, 0.5f);
animator.SetFloat("Sports", currentSpeed);
}
//计算体力值,根据当前的速度来判断角色时走还是跑还是站立不动
void CalculateTired()
{
if (currentSpeed <= walkSpeed && currentTired >= minTired)
{
//角色站立不动,疲劳值每秒-1
currentTired -= Time.deltaTime;
}
else if (currentSpeed >= runSpeed && currentTired <= maxTired)
{
//角色跑动,疲劳值+1
currentTired += Time.deltaTime;
}
else
{
//角色走动,疲劳值不变
return;
}
//将疲劳值限制在最大最小之间
currentTired = Mathf.Clamp(currentTired, minTired, maxTired);
}
(1)设置动画
打开角色的动画器,点击图层,新建一个图层命名位“States”,该图层来放角色疲惫动画。
点击新建States层右侧的齿轮,可以看到下面的面板内容
其中的权重:代表该层动画的播放的程度【我们通过将疲劳值与权重相关联来表示角色不同程度的疲惫】
在下面的Assets中新建一个Avatar遮罩,并命名
点开新建的遮罩,在右侧选择“人形”(因为是人形动画),我们的疲惫动画只显示在角色的头和躯干,所以只让头和躯干是绿色就可以。
【这里意思是在该层放置的动画只播放躯干和头部的动画,所以选择下面的疲惫动画时建议选择头部和躯干是前后摇动的,显示角色劳累。】
设置好后,将这个遮罩拖到上面新建States层级的遮罩中,将正在混合设置为Additive【想给角色添加特色但又不取代动画】
然后将准备好的疲惫动画放到States层的动画器中,要将动画的循环打开。
这样动画设置好了,接下来通过代码来设置体力值并将体力值与该层的权重相关联。
(2)脚本编写
打开上面的角色脚本,添加如下代码
private int tiredLayerIndex;
//关于TiredWeight根据自己情况设置值
private float TiredWeight = 6.0f;
void Start()
{
animator = GetComponent<Animator>();
//获取State动画层级
tiredLayerIndex = animator.GetLayerIndex("State");
}
在CalculateTired()最后一行添加
//将体力值与播放疲惫动画的权重相关联
animator.SetLayerWeight(tiredLayerIndex,currentTired/MaxTired*TiredWeight);
实现效果:
消耗体力,体力条出现。疲劳值为零,体力条消失。
跟随
不同疲劳值体力条显示颜色不同
(1)体力条样式制作
【原理,两层sprite,底层是绿色,上层是灰色,随着疲劳值增加,上层的填充从0开始增加到1】
准备一个白色圆环PNG,导入unity,制成Sprite(2D和UI)
在unity中创建UI——image,命名PowerBG,在源图像中拖入这个圆环,并把颜色改为绿色
在该图像下方在新建一个图像,命名ShowPower,将圆环拖进源图像
将ShowPower的图像类型设置为已填充,填充方式Radial 360,填充原点为顶部,填充总数设置为1,不勾选顺时针
这样做好了体力条样式
(2)体力显示,颜色变化
当体力消耗三分之一,体力条变成黄色
当体力消耗三分之二,体力条变成红色
新建一个脚本,挂载到PowerBG上
[SerializeField]
public Image progressCircle;
public BlackCoatControl showPowerObject;//要显示体力的游戏对象
private float currentTired;
private Image changeColor;
private float changColorIndex=0.3f;
private void Start()
{
changeColor = this.GetComponent<Image>();
currentTired = showPowerObject.CurrentTired;
}
private void FixedUpdate()
{
ToChange();
}
void ToChange()
{
currentTired = showPowerObject.CurrentTired;
ToChangeColor();
progressCircle.fillAmount = currentTired / showPowerObject.MaxTired;
}
//根据体力条不同值,像是不同颜色提示玩家体力耗尽
void ToChangeColor()
{
if (currentTired>=showPowerObject.MaxTired/3&¤tTired<showPowerObject.MaxTired*2/3)
{
changeColor.color = Color.Lerp(Color.green, Color.yellow, 0.7f);
}
if (currentTired>=showPowerObject.MaxTired*2/3)
{
changeColor.color = Color.Lerp(Color.yellow, Color.red, 0.7f);
}
}
返回unity,将挂载脚本对象的子物体ShowPower拖到Progress Circle
将游戏对象拖到Show Power Object中
(3)体力条跟随
新建一个脚本挂载到上面的PowerBG对象上
public Transform followed;
private Vector3 offset;
private Vector3 followedScreen;
private bool isRun;
private void Awake()
{
//使用协程为了防止当播放画面变化,体力条与人物间距离出现偏差。
StartCoroutine(Wait());
}
void Update()
{
if (isRun)
{
//将要跟随对象得世界坐标位置转化为屏幕空间
followedScreen = Camera.main.WorldToScreenPoint(followed.transform.position);
transform.position = followedScreen;
transform.position = new Vector2(transform.position.x - offset.x, offset.y);
}
}
IEnumerator Wait()
{
yield return new WaitForSeconds(1f);
followedScreen = Camera.main.WorldToScreenPoint(followed.transform.position);
offset.x = followedScreen.x - transform.position.x;
offset.z = followedScreen.z - transform.position.z;
offset.y = transform.position.y;
isRun = true;
}
返回unity,将游戏对象或游戏对象的子级拖到Followed中,根据自己想要将体力条放的位置来设置。
(4)实现玩家消耗体力时,体力条才出现。不消耗时不显示
在玩家脚本中的添加:
public GameObject Show;
void ShowPowerUI()
{
if(currentTired!=0)
Show.SetActive(true);
else
{
Show.SetActive(false);
}
}
void FixedUpdate()
{
ShowPowerUI();
MovePlayer();
CalculateTired();
}
返回unity,在里面拖入上面的体力条对象
最后将PowerBG不显示
这样就完成了。
内容较多,哪里有问题感谢指出。