Bullet 预制件未到达给定目标
Bullet prefab doesn't go to given target
我正在开发我的第一款 FPS 游戏。我将尝试解释到目前为止我做了什么以及我为解决问题所做的努力。
有一个控制玩家的 FPS 控制器,并且玩家有一个武器。 Weapon 游戏对象有一个名为 ButtetSpown 的子对象。我用一个平原作为地面,并添加了一些立方体作为墙壁。那是我的基本设置。我正在通过光线投射收集目标位置。
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 ());
}
}
子弹脚本更新方法。子弹有刚体连接并且 iskinematic 为真。
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) 点。我通过调试bullet targetPosition和hit point position检查了ray hit point和bullet target position
Debug.Log("hit " + hit.point );
Debug.Log("Target " + targetPosition);
谁能告诉我我做错了什么?我应该改变什么?
我在 PoolManager 脚本中发现了问题。 TryActive 方法的 return 语句应从
更改
return PoolItems[ItemIndex].transform;
至
return transform.GetChild(i).transform;
我正在开发我的第一款 FPS 游戏。我将尝试解释到目前为止我做了什么以及我为解决问题所做的努力。
有一个控制玩家的 FPS 控制器,并且玩家有一个武器。 Weapon 游戏对象有一个名为 ButtetSpown 的子对象。我用一个平原作为地面,并添加了一些立方体作为墙壁。那是我的基本设置。我正在通过光线投射收集目标位置。
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 ());
}
}
子弹脚本更新方法。子弹有刚体连接并且 iskinematic 为真。
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) 点。我通过调试bullet targetPosition和hit point position检查了ray hit point和bullet target position
Debug.Log("hit " + hit.point );
Debug.Log("Target " + targetPosition);
谁能告诉我我做错了什么?我应该改变什么?
我在 PoolManager 脚本中发现了问题。 TryActive 方法的 return 语句应从
更改return PoolItems[ItemIndex].transform;
至
return transform.GetChild(i).transform;