实现效果
俯视视角下,wasd控制人物移动,人物可进行360°流畅转身。
知识点
角度计算:绕y轴软转到direction方向需要转多少度
float angle = Vector3.Angle(new Vector3(0, 1, 0), direction);
在局部坐标系中旋转到(0, 0 , angle)
transform.localEulerAngles = new Vector3(0, 0, angle);
不使用transform.Rotate(vec3)的原因
Rotate(vec3)为旋转vec3角度(相对角度),只要按键按下左右键就会执行,会达到令人凌乱的效果。
localEulerAngles(vec3)为旋转到vec3角度(绝对角度),如果已经到达该角度,再怎么按左右键都不会过度旋转。
代码
- 挂载在玩家Object上
// Attached on playerObj
public class PlayerController : MonoBehaviour
{
public float speed = 1.0f;
public Animator anim;
private void Start()
{
anim = GetComponentInChildren<Animator>();
}
void FixedUpdate()
{
float xPosition = Input.GetAxis("Horizontal") * speed;
float yPosition = Input.GetAxis("Vertical") * speed;
if (Input.GetKey("a")||Input.GetKey("d")||Input.GetKey("w")||Input.GetKey("s"))
{
transform.Translate(xPosition, yPosition, 0);
//animator.SetBool("isWalking", true);
}
anim.SetFloat("speed", Mathf.Abs(xPosition)+Mathf.Abs(yPosition));
//else animator.SetBool("isWalking", false);
}
此脚本只负责移动玩家Object,不管玩家如何旋转。
注意:若带有RigidBody组件,必须使用FixedUpdate(),否则会解锁奇奇怪怪的移动方式。
- 挂载在玩家Object子物体,sprite上(带有玩家sprite和animator)
// Attached on player-spriteObj
public class SpriteSpinner : MonoBehaviour
{
SpriteRenderer spriteRenderer;
Vector3 direction;
bool moveV;
bool moveH;
// Start is called before the first frame update
void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void Update()
{
direction.x = Input.GetAxis("Horizontal");
direction.y = Input.GetAxis("Vertical");
if(direction.x == 0 && direction.y != 0){
moveV = true;
moveH = false;
}
else if(direction.y == 0 && direction.x != 0){
moveH = true;
moveV = false;
}
else{
moveH = false;
moveV = false;
}
if(moveV){
int rotateY = direction.y > 0 ? 0 : 180;
transform.localEulerAngles = new Vector3(0, 0, rotateY);
}
else if(moveH){
int rotateX = direction.x > 0 ? -90 : 90;
transform.localEulerAngles = new Vector3(0, 0, rotateX);
}
else{
int signX = direction.x < 0 ? 1 : -1;
float angle = signX * Vector3.Angle(new Vector3(0, 1, 0), direction);
if(angle != 0) transform.localEulerAngles = new Vector3(0, 0, angle);
}
}
}
此脚本只负责旋转玩家带有sprite组件的子物体(即子物体的旋转不会影响玩家整体的移动方向)
Bug & 待修改
停止控制后会自动旋转一定角度