【问题标题】:Instantiate a bullet towards player position向玩家位置实例化子弹
【发布时间】:2019-05-23 23:23:22
【问题描述】:

在输入左键 (Fire1) 时,弹丸从 projectileSpawn 位置生成。在右键单击(Fire2)时,我想让弹丸“反向”射击并从 projectileSpawnTwo 位置开始并返回到初始 projectileSpawn 位置。它目前向前射击,但我希望弹丸产生回一个确切的位置。

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

public class PlayerWeapon : MonoBehaviour 
{
    public GameObject projectilePrefab;

    public GameObject projectileTwoPrefab;

    public Transform projectileSpawn;
    public Transform projectileSpawnTwo;

    public float projectileSpeed = 30;  

    void Update () 
    {
        if (Input.GetButtonDown("Fire1")) 
        {
            Fire();
        }

        if (Input.GetButtonDown("Fire2")) 
        {
            Fire2();
        }
    }

    private void Fire() 
    {
        GameObject projectile = Instantiate(projectilePrefab);

        Physics.IgnoreCollision(projectile.GetComponent<Collider>(),
                                projectileSpawn.parent.GetComponent<Collider>()); 

        projectile.transform.position = projectileSpawn.position;

        var rot = projectile.transform.rotation.eulerAngles;

        projectile.transform.rotation = Quaternion.Euler(rot.x, transform.eulerAngles.y, rot.z);

        projectile.GetComponent<Rigidbody>().AddForce(projectileSpawn.forward * projectileSpeed, ForceMode.Impulse);       
    }

    private void Fire2()
    {
        GameObject projectile = Instantiate(projectileTwoPrefab);

        Physics.IgnoreCollision(projectile.GetComponent<Collider>(),
                                projectileSpawnTwo.parent.GetComponent<Collider>()); 

        projectile.transform.position = projectileSpawnTwo.position;

        var rot = projectile.transform.rotation.eulerAngles;

        projectile.transform.rotation = Quaternion.Euler(rot.x, transform.eulerAngles.y, rot.z);

        projectile.GetComponent<Rigidbody>().AddForce(projectileSpawnTwo.forward * projectileSpeed, ForceMode.Impulse);
    }
}

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    由于这两种方法非常相似,因此您可以稍微概括一下您的方法

    private Collider projectileSpawnParentCollider;
    
    privtae enum FireType
    {
        One,
        Two
    }
    
    private void Awake()
    {
      // this hould probably done only once to be more efficient
      projectileSpawnParentCollider = projectileSpawn.parent.GetComponent<Collider>();
    }
    
    private void Update()
    {
        if (Input.GetButtonDown("Fire1")) 
        {
            Fire(FireType.One);
        }
    
        if (Input.GetButtonDown("Fire2")) 
        {
            Fire(FireType.Two);
        }
    }
    
    private void Fire(FireType fireType) 
    {
        var position = fireType == FireType.One ? projectileSpawn.position : projectileSpawnTwo.position;
    
        var rot = projectile.transform.rotation.eulerAngles;
    
        var rotation = Quaternion.Euler(rot.x, transform.eulerAngles.y, rot.z);
    
        // pass the position and rotation alraedy
        GameObject projectile = Instantiate(projectilePrefab, position, rotation);
    
        Physics.IgnoreCollision(projectile.GetComponent<Collider>(), projectileSpawnParentCollider);
    
    
        var forceDirection = fireType == FireType.One ? projectileSpawn.forward : (projectileSpawn.position - projectileSpawnTwo.position).normalized;
    
        projectile.GetComponent<Rigidbody>().AddForce(forceDirection * projectileSpeed, ForceMode.Impulse);
    }
    

    projectileSpawn.position - projectileSpawnTwo.position
    

    返回一个从projectileSpawnTwo.position 指向projectileSpawn.position 的向量。使用normalized 返回一个方向相同但带有magnitude = 1 的向量。


    但是,请注意,这只有在玩家在第二次射击后没有移动时才有效。如果玩家可以移动,您可能应该实现另一个组件,以使子弹对象实际跟随玩家位置。

    您可以使用Quaternion.LookRotationRigidbody.MoveRotation 编写一个单独的组件,例如

    public class FollowPlayer : MonoBehaviour
    {
        public Transform PlayerTransform;
        public RigidBody rigiBody;
        public speed;
    
        private void Awake()
        {
           rigidBody = GetComponent<RigidBody>();
        }
    
        private void LateUpdate()
        {
            if(!PlayerTrasnform) return;
    
            var rotation = Quaternion.LookRotation(PlayerTransform.position - transform.position, Vector3.up);
    
            rigidBody.MoveRotation(rotation);
            rigidBody.velocity = (PlayerTransform.position - transform.position).normalized * speed;
        }
    }
    

    并在您的脚本中添加组件以防两个类似

    private void Fire(FireType fireType) 
    {
        var position = fireType == FireType.One ? projectileSpawn.position : projectileSpawnTwo.position;
    
        var rot = projectile.transform.rotation.eulerAngles;
    
        var rotation = Quaternion.Euler(rot.x, transform.eulerAngles.y, rot.z);
    
        // pass the position and rotation alraedy
        GameObject projectile = Instantiate(projectilePrefab, position, rotation);
    
        Physics.IgnoreCollision(projectile.GetComponent<Collider>(), projectileSpawnParentCollider);
    
        if(fireType == FireType.One)
        {
            projectile.GetComponent<Rigidbody>().AddForce(projectileSpawn.forward * projectileSpeed, ForceMode.Impulse);
        }
        else
        {
            var follow = projectile.AddComponent<FollowPlayer>();
            follow.speed = projectileSpeed;
            follow.PlayerTransform = YourPlayerTransform; // or probably projectileSpawn
        }
    }
    

    注意:在智能手机上输入,所以没有保修,但我希望这个想法很清楚。

    【讨论】:

    • 非常感谢!跟随玩家实际上会更可取。你知道用当前代码实现这个的最简单方法吗?我觉得这是一个如此简单的解决方案,但似乎无法使代码工作
    • @CharlotteBarnekow 查看我的更新。我没有测试它,但类似的东西应该可以做到。问题是在这里处理 RigidBody 有点困难;)
    • 非常感谢您抽出宝贵时间提供帮助!我用我的代码实现了你的代码,它现在可以工作了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多