【问题标题】:How can I flip a sprite of an AI enemy character to face the direction its moving in?如何翻转 AI 敌方角色的精灵以面向其移动方向?
【发布时间】:2019-04-18 06:47:28
【问题描述】:

我正在尝试制作一个可以从一个点移动到另一个点的巡逻 AI 角色。

巡逻部分完美运行。然而,问题是精灵只面向右边。当它转动时,精灵保持朝向相同的方向。

我尝试使用transform.rotatetransform.rotationtransform.Quaternion 更改变换旋转并创建一个变量来存储旋转值,但它们都将错误返回。错误通常是由于旋转/旋转功能与我尝试过的任何尝试都不兼容。

这是我的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// To do:
/// - make rotation of enemy sprite work when reaching the end of patrol area
/// - create attack function
/// </summary>


public class Enemy : MonoBehaviour
{
    public int health;
    public float speed;
    public GameObject bloodEffect;
    public Transform[] moveSpots;               //patrol spots
    public float startWaitTime;                 //start countdown till move to next spot

    private Rigidbody2D rb;
    private Animator anim;
    private int randomSpot;                     //number of patrol spots 
    private float waitTime;                     //how long enemy stays at patrol spot for

    // Start is called before the first frame update
    void Start()
    {
        waitTime = startWaitTime; //make waittime equal to startwaittime
        anim = GetComponent<Animator>();
        randomSpot = Random.Range(0, moveSpots.Length); //choose a random first spot 
    }

    // Update is called once per frame
    void Update()
    {

        Vector3 spriteRotation = new Vector3(0, randomSpot, 0);
        transform.position = Vector2.MoveTowards(transform.position, moveSpots[randomSpot].position, speed * Time.deltaTime); //move toward first patrol area
        transform.eulerAngles = spriteRotation;

        if (Vector2.Distance(transform.position, moveSpots[randomSpot].position) < 0.5f) //asks if patrol point is further that .5f away from enemy
        {
            if (waitTime <= 0) //if waitTime less than or equal to 0
            {

                randomSpot = Random.Range(0, moveSpots.Length); //picks new patrol point
                waitTime = startWaitTime; //restarts countdown clock
            }
            else
            {
                waitTime -= Time.deltaTime; //counts down clock till next point
            }
        }

        if (health <= 0)
        {
            Destroy(gameObject);
        }
    }


    public void TakeDamage(int damage)
    {
        Instantiate(bloodEffect, transform.position, Quaternion.identity);
        Debug.Log("Blood effect played");
        health -= damage;
        Debug.Log("Damage Taken");
    }
}

此代码的预期结果是会选择一个随机点,并且 AI 将向该选定点移动。一旦到达那里,它将在指定的时间内保持空闲状态,然后转向并移动到新位置。

实际结果与预期大致相同,只是精灵没有转身而是继续面向右侧,即使 AI 向左移动。

Image of area 敌人是暗红色立方体,移动点是敌人巡逻的点。当它到达左侧时,他应该向右转并返回,但这不是发生的情况,而是他只是来回移动而不旋转。我试过 SpriteRenderer.flipX 路线,它只工作一次,然后坚持那个方向。

【问题讨论】:

  • 无法想象你的意思,需要一张照片^^,但如果我理解正确,请寻找一些 faceToScripts 或 LookAtScripts,这样你的角色就会看到你引用他的点跨度>
  • 如果你想翻转精灵,我不会旋转它,而是将它的 X 缩放值设置为 -1。
  • 我记得还有一个翻转属性

标签: c# unity3d quaternions image-rotation


【解决方案1】:

SpriteRenderer 组件有一个 Flip 属性,您可以使用它。

你可以在代码中访问它

SpriteRenderer.flipX = true;

它只会翻转精灵而不会改变其他任何东西,所以仔细检查你的碰撞器是否仍然在正确的空间:) See more in the documentation 祝你好运

【讨论】:

    【解决方案2】:

    randomSpot 是索引而不是角度。所以使用

    transform.eulerAngles = new Vector3(0, randomSpot, 0);
    

    对我来说没有任何意义......


    除了旋转,您还可以使用负比例来翻转 sprite/Image,例如

    // Update is called once per frame
    private void Update()
    {
        // however you determin if facing left or right
        // you e.g. simply check whether the target position 
        // is left or right of you
        var difference = moveSpots[randomSpot].position - transform.position;
        var isFacingRight = difference.x > 0; 
    
        if (isFacingRight && transform.localScale.x < 0
            || !isFacingRight && transform.localScale.x > 0)
        {
            FlipSprite();
        }
    }
    
    private void FlipSprite()
    {
        // invert the local X-axis scale
        transform.localScale = new Vector3(-spriteTransform.localScale.x, spriteTransform.localScale.y, spriteTransform.localScale.z);
    }
    

    示例中使用的脚本

    private void Update()
    {
        // works only in a ScreenOverlay Canvas
        var targetPosition = Input.mousePosition;
    
        var difference = targetPosition - transform.position;
        var isFacingRight = difference.x > 0 ? true : false;
    
        if (isFacingRight && transform.localScale.x < 0
            || !isFacingRight && transform.localScale.x > 0)
        {
            FlipSprite();
        }
    
        // simply only move left or right on the x-axis towards the mouse
        transform.position = Vector3.MoveTowards(transform.position, new Vector3(targetPosition.x, 218, 0), Time.deltaTime * 100);
    }
    
    private void FlipSprite()
    {
        // invert the local X-axis scale
        transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
    }
    

    【讨论】:

      【解决方案3】:

      你可以试试:

      if (moveSpot[randomSpot].transform.position.x > transform.position.x) {
          transform.localScale = new Vector3(-1, 1, 1);
      }
      else {
          transform.localScale = new Vector3(1, 1, 1);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 2022-07-26
        • 2021-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多