【问题标题】:Unity 3D How to setup Turret Auto Aim? C#Unity 3D 如何设置炮塔自动瞄准? C#
【发布时间】:2015-07-20 04:08:19
【问题描述】:

我不想实现的是让我的炮台旋转并跟随“敌人”。

此刻它检测到了敌人,但它没有旋转,我不知道为什么。

它是我拖入的预制件,必须有更好的方法来做到这一点吗?请问大家有什么建议吗?

目前子弹永远不会触发,但是日志 Shoot and do...并且旋转不起作用。

这就是我所拥有的

using UnityEngine;
using System.Collections;

public class TurretController : MonoBehaviour {

    public Rigidbody bulletPrefab;
    private Transform target;
    private GameObject bullet;
    private float nextFire;
    private Quaternion targetPos;

    void OnTriggerEnter(Collider otherCollider) {
        if (otherCollider.CompareTag("Enemy"))
        {
            Debug.Log ("in");
            target = otherCollider.transform;
            StartCoroutine ("Fire");
        }
    }

    void  OnTriggerExit(Collider otherCollider) {
        if (otherCollider.CompareTag("Enemy"))
        {
            Debug.Log ("out");
            target = null;
            StopCoroutine("Fire"); // aborts the currently running Fire() coroutine
        }
    }

    IEnumerator Fire()
    {
        while (target != null)
        {
            nextFire = Time.time + 0.5f;
            while (Time.time < nextFire)
            {
                // smooth the moving of the turret
                targetPos = Quaternion.LookRotation (target.position);
                transform.rotation = Quaternion.Slerp(transform.rotation, targetPos, Time.deltaTime * 5);
                yield return new WaitForEndOfFrame();
            }
            // fire!
            Debug.Log ("shoot");
            bullet = Instantiate(bulletPrefab, transform.position, transform.rotation) as GameObject;
            //bullet.rigidbody.velocity = transform.forward * bulletSpeed;
        }
    }
}

我试图用这个来改变实例化部分

bullet = (GameObject)Instantiate(bulletPrefab, transform.position, transform.rotation);
            bullet.GetComponent<Bullet>().target = target.transform;

但是我只是收到类似“InvalidCastException:无法从源类型转换为目标类型。 TurretController+c__Iterator0.MoveNext () (at Assets/Scripts/TurretController.cs:44)"

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    顺便说一句,这是我在项目中使用的炮塔旋转代码(经许可共享):

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class Turret : MonoBehaviour
    {
        [SerializeField]
        private float turnRateRadians = 2 * Mathf.PI;
    
        [SerializeField]
        private Transform turretTop; // the gun part that rotates
    
        [SerializeField]
        private Transform bulletSpawnPoint;
    
        private Enemy target;
    
        void Update()
        {
            TargetEnemy();
        }
    
        void TargetEnemy()
        {
            if (target == null || target.health <= 0)
                target = Enemy.GetClosestEnemy(turretTop, filter: enemy => enemy.health > 0);
    
            if (target != null)
            {
                Vector3 targetDir = target.transform.position - transform.position;
                // Rotating in 2D Plane...
                targetDir.y = 0.0f;
                targetDir = targetDir.normalized;
    
                Vector3 currentDir = turretTop.forward;
    
                currentDir = Vector3.RotateTowards(currentDir, targetDir, turnRateRadians*Time.deltaTime, 1.0f);
    
                Quaternion qDir = new Quaternion();
                qDir.SetLookRotation(currentDir, Vector3.up);
                turretTop.rotation = qDir;
            }
        }
    }
    
    class Enemy : MonoBehaviour
    {
        public float health = 0;
    
        private static HashSet<Enemy> allEnemies = new HashSet<Enemy>();
    
        void Awake()
        {
            allEnemies.Add(this);
        }
    
        void OnDestroy()
        {
            allEnemies.Remove(this);
        }
    
        /// <summary>
        /// Get the closest enemy to some transform, optionally filtering
        /// (for example, enemies that aren't dead, or enemies of a certain type).
        /// </summary>
        public static Enemy GetClosestEnemy(Transform referenceTransform, System.Predicate<Enemy> filter=null)
        {
            // Left as an exercise for the reader.
            // Remember not to use Vector3.Distance in a loop if you don't need it. ;-)
    //      return allEnemies[0];
        }
    }
    

    【讨论】:

    • 非常感谢,伙计,我会尽快解决这个问题。真的很有帮助,因为我在用 C# 编写的互联网上找不到太多内容
    • 欢迎您!我实际上不记得为什么我们使用SetLookRotation() 而不是transform.forward=,所以你可以尝试两种方式。
    • 我现在使用 transform.forward,我的代码有效,但是我没有任何逻辑来处理多个敌人,当我的塔正在射击并且另一个走进它时,它会立即捕捉到它。我想要做的是添加类似于 BloonsTD 游戏的逻辑,用户可以选择塔是攻击敌人最远的地方,还是首先攻击最强或最弱的......再次感谢。
    • 这听起来很容易改变。现在一旦它选择了一个目标,它就会一直向那个敌人射击,直到它死亡。这也可以改变。
    【解决方案2】:

    第一个问题:子弹预制件。变量类型为RigidBody。如果要将其视为游戏对象,则该变量必须是游戏对象。或者您可以实例化它,转换为RigidBody,然后使用.gameObject 访问器。像这样:

    ((RigidBody)Instantiate(theRigidbody)).gameObject
    

    第二个问题:从简单的旋转开始。如果它不起作用,请不要花哨。从这样的事情开始(立即向目标旋转):

    Vector3 targetDirection = target.transform.position - transform.position;
    targetDirection.y = 0; // optional: don't look up
    transform.forward = targetDirection;
    

    如果它有效,则添加一些额外的复杂性,直到它完全符合您的要求。如果你没有弄明白,请在星期一给我留言(评论)。我写了炮塔瞄准代码(包括最大旋转速度),我想我的老板不会介意我上传它。

    【讨论】:

    • 关于最后一段,如果您不是 100% 确定,那绝对是您应该询问您的律师的问题。
    • 是的,我已经在键盘上敲了几个小时的头,试图把它弄好哈哈。如果你能在星期一把它寄给我,我会很高兴的。:P
    • 另外,是的,请确保你不会给我惹上麻烦.. 哈哈,我试过了,我尝试将其更改为 GameObject 而不是刚体并更改瞄准代码,不,它似乎旨在第二,但随后抛出错误,仍然没有拍摄。另外我刚刚意识到我的子弹是一个朝向目标的预制件,最初我让我的炮塔设置了子弹的目标,但我试图破解这段代码我从未尝试将目标传递给子弹,检查几分钟后编辑,我将发布更新的代码。
    • 我已经更改为尝试一些不同的代码,现在我得到一个错误“InvalidCastException:无法从源类型转换为目标类型。TurretController+c__Iterator0.MoveNext () (在 Assets/Scripts/ TurretController.cs:47) " jsfiddle.net/45quae96
    • 你这个摇滚伙伴,它似乎奏效了我重新链接了脚本和子弹,然后它开始射击了。很好,谢谢你,老兄......我仍然很想看看你是怎么做到的我被黑的代码太可怕了哈哈
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    相关资源
    最近更新 更多