在阅读“Unity in Action”一书时,我偶然发现了一个问题。在第 3 章结束时,您将了解一个简单的 fps 游戏的基础知识。它基本上是一个简单的小关卡中的玩家(连接到它的相机),它只存在于形成墙壁和地板等的许多立方体中。这些立方体上都有盒子碰撞器。现在玩家还可以射击移动的敌人,这些敌人也可以射击。这是由 Raycast/RaycastHit 完成的。所有这一切都很完美,所以我想添加一些重新组装弹孔的东西,只需在火球(这是敌人和玩家射击的对象)击中它的墙上实例化一个黑色球体对象。这可行,但有时火球物体只是穿过墙壁。万一后面还有一堵墙,
我将火球中的速度从 20 改为 10,然后再改回 20,速度为 10 时,成功率约为 19/20,而速度为 20 时,成功率约为 6/10。
这是火球的代码,它应该检查它是否击中玩家(然后扣除生命值,效果很好)或击中敌人(然后敌人倒下,也可以正常工作)或击中墙壁,在这种情况下应该创建球体。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fireball : MonoBehaviour {
public float speed = 10.0f;
public int damage = 1;
[SerializeField] private GameObject wallHit;
private GameObject _wallHit;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.Translate(0,0, speed * Time.deltaTime);
}
void OnTriggerEnter(Collider other){
RaycastHit hit;
PlayerCharacter player = other.GetComponent<PlayerCharacter>();
ReactiveTarget target = other.GetComponent<ReactiveTarget>();
WallBehavior wall = other.GetComponent<WallBehavior>();
if(player != null){
player.Hurt(damage);
}
if(target != null){
target.ReactToHit();
}
if(wall != null){
if(Physics.Raycast(transform.position, transform.forward, out hit)){
wall.WallWasHit(hit);
}
}
Destroy(this.gameObject);
}
}
如您所见,我尝试的一件事是给每面墙一个 WallBehavior 脚本,如下所示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WallBehavior : MonoBehaviour {
[SerializeField] private GameObject wallHit;
private GameObject _wallHit;
static int count = 0;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void WallWasHit(RaycastHit hit){
count++;
Debug.Log("Wall was hit: " + count);
_wallHit = Instantiate(wallHit) as GameObject;
_wallHit.transform.position = hit.point;
}
}
但是到目前为止,我试图理解为什么这种情况很少发生的尝试都没有成功,我希望有人能帮助我解决这个问题,因为在我继续阅读这本书之前,我觉得这可能对我的学习至关重要!提前致谢。如果需要更多信息,我很乐意提供。请参阅下图以更好地可视化该问题。
编辑:如答案中所述,我相应地替换了火球脚本,但我不确定如何同样更改以下脚本。这个脚本在我的相机上,它在我的播放器对象上。在更新函数中,火球被实例化并被赋予了运动,所以我猜这会导致问题吗?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RayShooter : MonoBehaviour {
private Camera _camera;
[SerializeField] private GameObject fireballPrefab;
private GameObject _fireball;
void Start () {
_camera = GetComponent<Camera>();
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
void OnGUI(){
int size = 12;
float posX = _camera.pixelWidth/2 - size/4;
float posY = _camera.pixelHeight/2 - size/2;
GUI.Label(new Rect(posX, posY, size, size), "X");
}
// Update is called once per frame
void Update () {
if(Input.GetMouseButtonDown(0)){
Vector3 point = new Vector3(_camera.pixelWidth/2, _camera.pixelHeight/2, 0);
_fireball = Instantiate(fireballPrefab) as GameObject;
_fireball.transform.position = transform.TransformPoint(Vector3.forward * 1.5f);
_fireball.transform.rotation = transform.rotation;
Ray ray2 = _camera.ScreenPointToRay(point);
RaycastHit hit;
if(Physics.Raycast(ray2, out hit)){
GameObject hitObject = hit.transform.gameObject;
ReactiveTarget target = hitObject.GetComponent<ReactiveTarget>();
if(target !=null){
target.ReactToHit();
}
}
}
}
}