要在角色开始移动时将动画切换为 walk,可以通过添加一个 Animator 组件和相应的 Animator Controller 来实现。首先,在 Unity 中创建一个 Animator Controller,然后将其分配给角色的 Animator 组件。在这个控制器中,创建两个动画状态:walk 和 idle,并将它们分别与名为 IsWalking 和 IsIdle 的布尔参数关联起来。
接下来,在 PlayerController1 脚本中,在 MoveToTarget 协程中设置 IsWalking 参数为 true,在协程结束时将其设回 false。还可以使用 GetAxisRaw 函数检测玩家是否按下了左右箭头键(或者 A/D 键),并设置相应的参数来播放行走动画。
以下是修改后的代码:
using UnityEngine;
using System.Collections;
public class PlayerController1 : MonoBehaviour
{
public GameObject circlePrefab;
private GameObject currentCircle;
private Vector3 targetPosition;
private bool facingRight = true;
// 新增变量:限制角色移动范围
public Rect moveRange;
Coroutine currentCoroutine;
// 新增变量:Animator 组件
private Animator animator;
void Start()
{
// 获取角色上的 Animator 组件
animator = GetComponent<Animator>();
}
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Began:
if (IsTouchedOnPlayer(touch.position))
{
currentCircle = Instantiate(circlePrefab, transform.position, Quaternion.identity);
return;
}
break;
case TouchPhase.Moved:
if (currentCircle != null)
{
Vector3 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
touchPos.z = 0;
currentCircle.transform.position = touchPos;
}
break;
case TouchPhase.Ended:
if (currentCircle != null)
{
HandleTouchEndedOrCanceled(touch);
Destroy(currentCircle);
}
break;
case TouchPhase.Canceled:
break;
}
}
// 新增:检测玩家是否按下左右箭头键(或者 A/D 键)
float horizontalInput = Input.GetAxisRaw("Horizontal");
animator.SetBool("IsWalking", horizontalInput != 0);
}
private bool IsTouchedOnPlayer(Vector2 screenPosition)
{
Vector2 worldPosition = Camera.main.ScreenToWorldPoint(screenPosition);
Collider2D[] colliders = GetComponents<Collider2D>();
foreach (var collider in colliders)
{
if (collider.OverlapPoint(worldPosition))
{
return true;
}
}
return false;
}
void HandleTouchEndedOrCanceled(Touch touch)
{
if (!IsTouchedOnPlayer(touch.position))
{
Vector2 targetPos = Camera.main.ScreenToWorldPoint(touch.position);
// 新增限制:将目标位置限制在 moveRange 范围内
targetPosition.x = Mathf.Clamp(targetPos.x, moveRange.xMin, moveRange.xMax);
targetPosition.y = Mathf.Clamp(targetPos.y, moveRange.yMin, moveRange.yMax);
if (currentCoroutine != null)
StopCoroutine(currentCoroutine);
currentCoroutine = StartCoroutine(MoveToTarget());
}
}
IEnumerator MoveToTarget()
{
float moveSpeed = 2.5f;
float bufferDistance = 0.01f;
Vector3 targetDirection;
// 新增:设置 IsWalking 参数为 true
animator.SetBool("IsWalking", true);
while (Vector3.Distance(transform.position, targetPosition) > bufferDistance)
{
if (transform.position == targetPosition)
yield break;
// 新增限制:检查角色是否超出了移动范围
Vector3 clampedPos = transform.position;
clampedPos.x = Mathf.Clamp(clampedPos.x, moveRange.xMin, moveRange.xMax);
clampedPos.y = Mathf.Clamp(clampedPos.y, moveRange.yMin, moveRange.yMax);
transform.position = clampedPos;
targetDirection = (targetPosition - transform.position).normalized;
if (targetDirection.x > 0 && !facingRight)
{
Flip();
}
else if (targetDirection.x < 0 && facingRight)
{
Flip();
}
if (Vector3.Distance(transform.position, targetPosition) < moveSpeed * Time.deltaTime)
{
transform.position = targetPosition;
yield break;
}
transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
yield return null;
}
// 新增:设置 IsWalking 参数为 false
animator.SetBool("IsWalking", false);
}
void Flip()
{
facingRight = !facingRight;
Vector3 scale = transform.localScale;
scale.x *= -1;
transform.localScale = scale;
}
}
现在,当玩家按下左右箭头键(或者 A/D 键)时,角色会播放行走动画。当角色到达目标位置后,动画将切换为闲置状态。