【问题标题】:Bullet prefab doesn't go to given target子弹预制件没有到达给定的目标
【发布时间】:2017-09-01 04:06:55
【问题描述】:

我正在开发我的第一款 FPS 游戏。我将尝试解释到目前为止我所做的事情以及我为解决我的问题所做的事情。

有一个 FPS 控制器控制玩家,并且有一个武器附在玩家身上。 Weapon 游戏对象有一个名为 ButtetSpown 的子对象。我使用平原作为地面,并添加了一些立方体作为墙壁。这是我的基本设置。我正在通过 Ray-casting 收集目标位置。

Vector3 rayOrigin = fpsCam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 0.0f));

我将这一点归功于实例化的子弹。下面是我的实例化过程代码(我已经去掉了枪动画代码)

void Update () {

        Vector3 rayOrigin = fpsCam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 0.0f));
        //Debug.DrawRay(rayOrigin, fpsCam.transform.forward * weaponRange, Color.green);

        if (Input.GetMouseButton(0) && Time.time > NextFire)
        { 
            NextFire = Time.time+ FireRate;

             if (Physics.Raycast(rayOrigin, fpsCam.transform.forward, out hit, weaponRange))
             {

               bulletclone = Instantiate(Bullet.transform, SpownPoint.transform.position, SpownPoint.transform.rotation) as Transform;
                bullet bulletScript = bulletclone.GetComponent<bullet>();
                bulletScript.target  = hit;
                Debug.Log("hit  " + hit.point );

                bulletScript.Accuracy = Accuracy;  

                if (hit.rigidbody != null)
                {
                    hit.rigidbody.AddForce(-hit.normal * 100);

                }
            }

            StartCoroutine( Firing ());

        }
}

Bullet 脚本更新方法。子弹有刚体附着,运动学是真的。

 Vector3 targetPosition=new Vector3(target.point.x + Random.Range(-Accuracy*2, Accuracy*2), target.point.y + Random.Range(-Accuracy/2, Accuracy/2), target.point.z);

Debug.Log("Target " + targetPosition);
rb.velocity = (targetPosition- transform.position).normalized * speed;

这很好用:子弹正确地找到了它的目标。问题发生在我添加 PoolManager 来控制预制件之后。我编写了 PoolManager 脚本。 PoolManager 脚本附加到 PoolManager 游戏对象。

PoolManager.cs

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

public class PoolManager : MonoBehaviour {

    [Tooltip("Maximum size of a gameobject can be in the pool")]
    public int MaxPoolSize = 20;
    public bool CanGrow = true;
    public GameObject[] PoolItems;
    public int[] ItemSize;
    private GameObject[] ActiveList;

    private Dictionary<string, int> Pooled = new Dictionary<string,int>();

    void Start () {
        //Add default prefabs as child of PoolManager gameobject
        for (int i = 0; i < PoolItems.Length; i++)
        {

            Pooled.Add(PoolItems[i].name ,0);
            for (int s = 0; s < ItemSize[i]; s++)
            {
                GameObject g = Instantiate(PoolItems[i]);
                g.name =  PoolItems[i].name;
                g.transform.parent = transform;
                g.SetActive( false);
                Pooled[g.name]=s + 1;
            }
        }

    }


    public Transform InstantiateObject(int ItemIndex, Vector3 Position, Quaternion Rotation)
    {
        Transform test = TryActive(ItemIndex, Position, Rotation);
        if (CanGrow == true && test == null)
        {

            if (Pooled[PoolItems[ItemIndex].name] < MaxPoolSize)
            {
                GameObject g = Instantiate(PoolItems[ItemIndex]);
                g.name = PoolItems[ItemIndex].name;
                g.transform.parent = transform;
                Pooled[g.name] = Pooled[g.name] + 1;
                return TryActive(ItemIndex, Position, Quaternion.identity);
            }


        }
        return test;
    }

    Transform TryActive(int ItemIndex, Vector3 Position, Quaternion Rotation)
    {
        if(PoolItems.Length==0) return null;

        int children = transform.childCount;
        for (int i = 0; i < children; ++i)
        {
            if (transform.GetChild(i).name == PoolItems[ItemIndex].name)
            {
                if (transform.GetChild(i).gameObject.activeInHierarchy == false)
                {
                    transform.GetChild(i).gameObject.SetActive(true);
                    transform.GetChild(i).position = Position;
                    transform.GetChild(i).rotation = Rotation;
                    return PoolItems[ItemIndex].transform;
                }
            }
        }


    }

}

所以所有实例化的预制件都将添加为 PoolManager 游戏对象的子级。

然后我更改了我的 Gun 脚本更新功能如下:

    if (Physics.Raycast(rayOrigin, fpsCam.transform.forward, out hit, weaponRange))
    {
          //1st parameter 0 is my bullet prefab which in PoolManager (PoolItems).
          // Only this code has changed from previous version 

                    bulletclone = poolmanager.InstantiateObject(0, SpownPoint.transform.position , SpownPoint.transform.rotation);

                    bullet bulletScript = bulletclone.GetComponent<bullet>();
                    bulletScript.target  = hit;
                    Debug.Log("hit  " + hit.point );

                    bulletScript.Accuracy = Accuracy;



                    if (hit.rigidbody != null)
                    {
                        hit.rigidbody.AddForce(-hit.normal * 100);

                    }
     }

问题是:子弹在 SpownPoint 中正确激活,但子弹并没有到达实际目标。它总是到达平原(地面)的(0,0,0)点。我通过调试子弹targetPosition和命中点位置检查了射线命中点和子弹目标位置。

Debug.Log("hit  " + hit.point );

Debug.Log("Target " + targetPosition);

谁能告诉我我在这里做错了什么?我应该改变什么?

【问题讨论】:

  • 当您使用对象池时,您是否检查过子弹的**速度**是否为0?
  • 速度是500,速度还可以
  • Vector3 targetPosition变成(0,0,0)不知道为什么

标签: c# unity3d unity5


【解决方案1】:

我在 PoolManager 脚本中发现了问题。 TryActive 方法的返回语句应该从

return PoolItems[ItemIndex].transform;

return transform.GetChild(i).transform;

【讨论】:

    猜你喜欢
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多