You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

3D等距旋转相机场景下2D角色精灵动画方向适配实现

3D等距视角玩家精灵动画方向适配问题

我正在尝试编写一套玩家精灵动画控制脚本,实现相机旋转时精灵动画方向自动调整的效果。当前项目为3D等距世界,每个朝向对应固定机位相机,场景中玩家为2D精灵,目前已独立编写玩家控制器、玩家动画、精灵渲染器三个脚本。

Player Controller(玩家控制器)

该控制器基于相机朝向实现移动逻辑,适配项目中多相机对应不同朝向的设计,代码如下:

public class PlayerController : MonoBehaviour
{
    public float speed = 5f;
    
void Update()
    {
        var moveInput = new Vector3(Input.GetAxis("Horizontal"), 0f , Input.GetAxis("Vertical"));

        moveInput = Camera.main.transform.TransformDirection(moveInput);
        moveInput.y = 0;
        moveInput = moveInput.normalized;
    
        transform.position += moveInput * Time.deltaTime * speed;
    }
}

Player Animation(玩家动画)

我参考的这套玩家动画脚本原本是为2D控制器编写的,逻辑清晰但无法直接适配当前3D场景,我需要明确如何正确添加行走动画逻辑,让脚本可以追踪玩家当前朝向,同步更新精灵渲染器的显示内容。现有代码如下:

public class PlayerAnimation : MonoBehaviour

{
    public Rigidbody2D body;
    public SpriteRenderer spriteRenderer;
    public List<Sprite> nSprite;
    public List<Sprite> neSprite;
    public List<Sprite> eSprite;
    public List<Sprite> seSprite;
    public List<Sprite> sSprite;
    public float frameRate;
    float idleTime;
    Vector3 direction;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        direction = new Vector3(Input.GetAxis("Horizontal"), 0f , Input.GetAxis("Vertical")).normalized;
        
        direction = Camera.main.transform.TransformDirection(direction);

        HandleSpriteFlip();

        List<Sprite> directionSprites = GetSpriteDirection();

        if(directionSprites != null) //holding direction
        {
            float playTime = Time.time - idleTime; //time since we sterted walking
            int totalFrames = (int)(playTime * frameRate); //total frames since we started
            int frame =  totalFrames % directionSprites.Count; //current frame

            spriteRenderer.sprite = directionSprites[frame];
        }
        else //holding nothing, input is neutral
        {
            idleTime = Time.time;
        }
    }

    void HandleSpriteFlip()
    {
        if (!spriteRenderer.flipX && direction.x < 0)
        {
            spriteRenderer.flipX = true;
        }
        else if (spriteRenderer.flipX && direction.x > 0)
        {
            spriteRenderer.flipX = false;
        }
    }

    List<Sprite> GetSpriteDirection()
    {

        List<Sprite> selectedSprites = null;

        if (direction.y > 0) //north
        {
            if (Mathf.Abs(direction.x) > 0) //east or west
            {
                selectedSprites = neSprite;
            }
            else {//neutral
                selectedSprites = nSprite;
            }
        }
        else if (direction.y < 0) //south
        {
            if (Mathf.Abs(direction.x) > 0) //east or west
            {
                selectedSprites = seSprite;
            }
            else {//neutral
                selectedSprites = sSprite;
            }
        }
        else //neutral
        {
            if (Mathf.Abs(direction.x) > 0) //east or west
            {
                selectedSprites = eSprite;
            }
        }

        return selectedSprites;
    }
}

Sprite Renderer(精灵渲染器)

该精灵渲染器脚本来自过往相关问题,可在静止物体上实现相机角度更新时的精灵切换效果,但我不清楚如何修改该脚本,使其可适配会移动、朝向动态变化的玩家对象。现有代码如下:

private SpriteRenderer spriteRenderer;

public Transform plane;
public Camera cam;

private const float step = 22.5f;

public Sprite N, NW, W, SW, S, SE, E, NE;
public void Start() => spriteRenderer = GetComponent<SpriteRenderer>();
public void Update()
{
    var projected = Vector3.ProjectOnPlane(cam.transform.forward, plane.up);
    var angle = Vector3.SignedAngle(projected, plane.forward, plane.up);
    
    var AbsAngle = Mathf.Abs(angle);
    
    if (AbsAngle < step) spriteRenderer.sprite = N;
    else if (AbsAngle < step*3) spriteRenderer.sprite = Mathf.Sign(angle) < 0 ? NW : NE;
    else if (AbsAngle < step*5) spriteRenderer.sprite = Mathf.Sign(angle) < 0 ? W : E;
    else if (AbsAngle < step*7) spriteRenderer.sprite = Mathf.Sign(angle) < 0 ? SW : SE;
    else spriteRenderer.sprite = S;
    
    Billboard(spriteRenderer.transform, cam);
}
public void Billboard(Transform character, Camera mainCamera)
{
    var dir = plane.position - mainCamera.transform.position;
    var LookAtRotation = Quaternion.LookRotation(dir);
    
    var LookAtRotationOnly_Y = Quaternion.Euler(character.rotation.eulerAngles.x, LookAtRotation.eulerAngles.y,character.eulerAngles.z);
    character.rotation = LookAtRotationOnly_Y;
}

内容的提问来源于stack exchange,提问作者naturalcrybaby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:24:21