沿光线投射移动对象

Move Object Along Raycast

我制作了一个从我的相机到点击对象点的 Raycast。然而,我试图让一个物体(在本例中是一颗子弹)沿着光线的路径飞行。由于矢量 3,无论您在对象上的哪个位置单击,它都会从相机直接向前飞行。我如何让它跟随射线?

C#

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

public class RaycastShot : MonoBehaviour {

public Camera camera;
private Ray ray;
private RaycastHit hit;
public GameObject bullet;
private GameObject createBullet;
private Collider collider;

void Update () {
    if (Input.GetMouseButtonDown (0)) {
        ray = camera.ScreenPointToRay (Input.mousePosition);

        createBullet = Instantiate (bullet, camera.transform.position, bullet.transform.rotation);
        createBullet.AddComponent<Rigidbody>();
        createBullet.GetComponent<Rigidbody>().AddRelativeForce (new Vector3(0, 1500, 0));
        createBullet.GetComponent<Rigidbody>().useGravity = false;
        collider = createBullet.GetComponent<Collider> ();
        Destroy (collider);

        if (Physics.Raycast (ray, out hit)) {

        }
    }
    Debug.DrawLine (ray.origin, hit.point, Color.red);
}
}

您可能希望使用 ray.direction 属性 而不是 (0,1500,0) 作为力的方向。

加力应该发生在 FixedUpdate 中,并且应该只在 Ray 击中某物时发生。你现在拥有它的地方可能不是最好的地方。

当然,首先要确保子弹在相机位置实例化。

Ray.direction 为您提供射线对象的 vector3 方向。如果你需要它击中的距离,你也可以使用ray.distance。

编辑:我现在在我的电脑旁边,所以这里有一个与您的评论相关的更详细的答案。

首先:这是我设置测试项目的方式:

我创建了一个预制子弹。这只是一个带有刚体的球体,附有我的 "BulletController" 脚本。预制件的要点是避免所有那些必须添加组件的行。出于测试目的,我将刚体设置为忽略重力并将其质量设置为 0.1。

接下来,我创建了 BulletController 脚本,它将附加到子弹预制件。

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

public class BulletController : MonoBehaviour {

    Rigidbody rb;
    public float bulletForce;
    bool firstTime = false;
    Vector3 direction;

    // Use this for initialization
    void Start () {
        rb = GetComponent<Rigidbody> ();
    }


    public void SetDirection (Vector3 dir) {
        direction = dir;
        firstTime = true;
    }

    void OnCollisionEnter () {
        //code for when bullet hits something
    }

    void FixedUpdate () {
        if (firstTime) {
            rb.AddForce (direction * bulletForce);
            firstTime = false;
        }
    }   
}

这个脚本是负责控制子弹的。将创建项目符号的(稍后)脚本并不关心它们之后会发生什么,因为它的工作只是创建项目符号。这个 BulletController 脚本负责处理创建的子弹。

主要部分是 SetDirection 方法,它告诉子弹向哪个方向行进。它还在其 FixedUpdate 方法中添加了一个一次性力,将它推向您刚刚设置的方向。 FixedUpdate 用于添加力等物理变化。不要使用更新来做这种事情。它将力乘以您设置的称为 "bulletForce".

的力

最后是 BulletListener 脚本,它只是附加到场景中的一个空游戏对象。此脚本负责侦听鼠标点击并向其创建子弹。

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

public class BulletListener : MonoBehaviour {

    public Camera mainCamera;
    public BulletController bulletPrefab;

    void Update () {
        if (Input.GetMouseButtonDown (0)) {

            //create ray from camera to mousePosition
            Ray ray = mainCamera.ScreenPointToRay (Input.mousePosition);

            //Create bullet from the prefab
            BulletController newBullet = Instantiate (bulletPrefab.gameObject).GetComponent<BulletController> ();

            //Make the new bullet start at camera
            newBullet.transform.position = mainCamera.transform.position;

            //set bullet direction
            newBullet.SetDirection (ray.direction);

        }

    }
}

在这个空游戏对象的检查器中,我添加了这个脚本,然后将摄像机和 bulletPrefab 拖到适当的字段中。一定要从文件夹中拖动预制件,而不是从场景中。因为这将使用预制件,而不是场景中的对象。

现在点击一下,你会看到子弹在飞!注意用小力测试一下就好了,以后再加大。

要摆脱的主要事情是拆分你的逻辑。一个脚本应该只负责一件事。例如,您的敌人也可能会发射子弹。您现在也可以为这些项目符号重用 bulletController 脚本。此外,假设您有不同大小或形状的子弹,您只需将 bulletcontroller 脚本拖到您为子弹制作的不同预制件上。这不会影响您的侦听器脚本,它仍会在您单击的位置创建项目符号。

如果有终点,则可以使用 MoveTowards 沿矢量移动:

Vector3 target = hit.point;
StartCoroutine(MoveAlong(target));


private IEnumerator MoveAlong(Vector3 target){
    while(this.transform.position != target){
         this.transform.position = MoveTowards(this.transform.position, target, step);
         yield return null;
    }
}