我按照这个视频得到了一个损坏脚本:https://www.youtube.com/watch?v=aSeE7u8Cs-I&list=PLZ1b66Z1KFKiaTYwyayb8-L7D6bdiaHzc&index=11
问题是,这是一把枪,出于某种原因,即使光线投射在前方,有时刀击中也不会记录。有没有办法让它使我面前的任何东西在点击/攻击时受到伤害?
这是我拥有的当前代码:
void Start()
{
animator = GetComponentInChildren<Animator>();
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Attack"))
{
StartCoroutine(Poke());
}
else
{
}
IEnumerator Poke()
{
RaycastHit knife;
//this line was causing weird delay but I can't remember 100% what it was for and if it's still needed
//isAttacking = true;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out knife))
{
knife.transform.SendMessage("DamageZombie", DamageAmount, SendMessageOptions.DontRequireReceiver);
}
animator.SetBool("isAttacking", true);
yield return new WaitForSeconds(.1f);
animator.SetBool("isAttacking", false);
}
}
} ```
试试这个:
bool isAttacking = false;
void Start() {
animator = GetComponentInChildren<Animator>();
}
void Update() {
if (Input.GetButtonDown("Attack")) {
StartCoroutine(Poke());
}
}
IEnumerator Poke() {
if(!isAttacking){
isAttacking = true;
RaycastHit knife;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out knife)) {
knife.transform.SendMessage("DamageZombie", DamageAmount, SendMessageOptions.DontRequireReceiver);
}
animator.SetBool("isAttacking", true);
yield return new WaitForSeconds(.1f);
animator.SetBool("isAttacking", false);
isAttacking = false;
}
}
还要记住,Physics.Raycast可能会使用LayerMask来检测物体,如果没有任何效果,请看一下。
好吧,您可能正在碰到其他碰撞体,一些没有附加任何组件的游戏对象,该组件具有称为DamageZombie
的方法。
有多种方法可以将光线投射限制为特定目标:
-
Physics.Raycast
需要其他参数最大距离 光线应检查碰撞的最大距离
。layerMask图层蒙版
,用于在投射光线时有选择地忽略碰撞体。因此,将目标敌人放在特定图层上,您已经可以将
Raycast
限制为仅击中这些,并且仅在它们足够接近时才击中它们:// Adjust here which layer(s) you want to hit via the Inspector public LayerMask targetLayers; ... if (Physics.Raycast(new Ray(transform.position, transform.forward), out var hit, 1f, (int)targetLayers)) { // Do something }
因此,这已经过滤了光线投射,并且仅击中
。1
单位范围内找到的第一个对象,并且仅在targetLayers
中配置的图层上 -
正如您所说,您想
hit everything
实际上可以使用Physics.RaycastAll
然后遍历所有命中var hits = Physics.RaycastAll(new Ray(transform.position, transform.forward), 1f, targetLayers); foreach(var hit in hits) { // Do something }
现在这基本上与以前相同,但现在击中
1
单元范围内和targetLayers
中配置的层上的每个对象。 -
使用标签,您可以进一步限制,并在光线投射后检查您击中的内容。
foreach(var hit in hits) { if(!hit.CompareTag("Zombie")) continue; // Do something }
最后一般不要使用SendMessage
!这是非常低效和不安全的..你永远不会知道你击中的对象是否有实现这种方法的组件......或者如果您在重命名方法后在每个地方都更改了此字符串......
而是真正获得您想要命中的组件!
var damageScript = hit.GetComponent<YOURSCRIPT>();
if(damageScript)
{
damageScript.DamageZombie(DamageAmount);
}