微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何对子弹进行击退 unity2D

如何解决如何对子弹进行击退 unity2D

我怎样才能做到当子弹击中一个物体时它会击退它并摧毁自己/消失?

我做了一些研究,但我找不到答案。我发现进行击退的唯一方法是让子弹正常击中物体,并以其质量给予击退,但子弹保持漂浮。

武器代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
    
public class Weapon : MonoBehavIoUr
{
    public Transform firePoint;
    public float fireRate = 15f;
    public GameObject bulletPrefab;
    public Transform  MuzzleFlashPrefab;
    public AudioSource sfx;
    private float nextTimetoFire = 0f;
    [HideInInspector] public audio currentGunData;
                   
    void Update() 
    {    
        if (Input.GetButton("Fire1") && Time.time >= nextTimetoFire)
        {
            nextTimetoFire = Time.time + 1f/fireRate;
            Shoot();
            //sound
            sfx.Stop();
            sfx.clip = currentGunData.gunshotSound;
            sfx.pitch = 1 - currentGunData.pitchRandomization + Random.Range(-currentGunData.pitchRandomization,currentGunData.pitchRandomization);
            sfx.Play();           
        }
    }
          
    void Shoot()
    {
        Instantiate(bulletPrefab,firePoint.position,firePoint.rotation);
        Transform clone = Instantiate (MuzzleFlashPrefab,firePoint.rotation) as Transform;
        clone.parent = firePoint;
        float size = Random.Range (0.02f,0.025f);
           
        clone.localScale = new Vector3 (size,size,size);
        Destroy (clone.gameObject,0.056f);
    }              
}

项目符号

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

public class bulet : MonoBehavIoUr
{       
    public float speed = 40f;
    public Rigidbody2D rb;
    
    // Start is called before the first frame update
    void Start()
    {
        rb.veLocity = transform.right * speed;
    }  
}

我正在拍摄的对象

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

public class stickmancontroler : MonoBehavIoUr
{
    public _Muscle[] muscles;
  
    // Update is called once per frame
    private void Update()
    {
        foreach (_Muscle muscle in muscles)
        {
            muscle.ActivateMuscle();
        }
    }
}

[System.Serializable]
public class _Muscle
{
   public Rigidbody2D bone;
   public float restRotation;
   public float force;

   public void ActivateMuscle()
   {
      bone.MoveRotation(Mathf.LerpAngle(bone.rotation,restRotation,force * Time.deltaTime));
    }  
}
   

我的击退尝试

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
    
public class Player : MonoBehavIoUr
{
    public float knockbackaPower = 100;
    public float knockbackDuration = 1;
    private static Player instance;
    private Rigidbody2D rb;
    private void Awake()
    {
        instance = this;
    }
    
    void Start()
    {            
    }
      
    void Update()
    {          
    }
          
    void OnTriggerEnter2D (Collider2D col)
    {
        if(col.gameObject.name == "bulet")
        {
            Debug.Log("hti");
        }       
    }      
    
    private void OnCollisionEnter2D(Collision2D other)
    {        
        if(other.gameObject.tag == "bullet")  
        {    
            StartCoroutine(Knockback(knockbackDuration,knockbackaPower,this.transform));
        }          
    }
         
    public IEnumerator Knockback(float knockbackDuration,float knockbackaPower,Transform obj)
    {
        float timer = 0;
    
        while (knockbackDuration > timer)
        {
            timer += Time.deltaTime;
            Vector2 direction = (obj.transform.position - this.transform.position).normalized;
            Debug.Log(rb);
            rb.AddForce(-direction * knockbackaPower);
        }
        yield return 0;
    }
}

解决方法

只有在子弹不再与物体碰撞后,您才能使用 OnCollisionExit2D() 销毁子弹。这样你就可以让子弹正常击中物体并用它的质量击退它。

,

如果你最后只yield,你的协程有什么用?如果您想将 while 循环分布在多个帧上,您必须在其中yield return null;

并且您可以在开始击退的那一刻简单地调用 Destroy(other.gameObject);,这样子弹在击中某物时立即被摧毁。只需预先缓存它的位置/击退方向,而不是预先重复计算每次迭代。

private void OnCollisionEnter2D(Collision2D other)
{  
    // In general rather use CompareTag instead of string ==
    // it is slightly faster and avoids typos since it would throw an error instead of silently fail       
    if(other.gameObject.ComapareTag("bullet")) 
    {  
        // Here you want to pass in the OTHER transform (the one of the bullet)
        // and NOT your own one!  
        StartCoroutine(Knockback(knockbackDuration,knockbackaPower,other.transform));
    }          
}
     
private IEnumerator Knockback(float knockbackDuration,float knockbackaPower,Transform bullet)
{
    var direction = (bullet.transform.position - transform.position).normalized;

    // As soon as you have all relevant values destroy the bullet immediately after a hit
    Destroy(bullet);

    var timer = 0f;  
    while (timer < knockbackDuration)
    {
        rb.AddForce(-direction * knockbackaPower);

        // You need to yield INSIDE the while loop
        // otherwise it is fully performed within one single frame
        timer += Time.deltaTime;
        yield return null;
    }
}

现在,如果不是让 onbects 碰撞(这应该已经在不需要协程的情况下造成一些击退),你实际上可以将其设为 触发器,而是实际计算来自 theass 和子弹的撞击速度

private IEnumerator OnTriggerEnter2D(Collider2D other)
{
    if(!other.CompareTag("bullet") || !other.TryGetComponent<Rigidbody2D>(out var bulletRb)) yield break; 

    // Calculate the knock force caused by the bullet's mass and velocity
    var speedSqr = bullerRb.velcotiy.sqrMagnitude;
    var direction = bullerRb.velcotiy.normalized;
    var force = 0.5f * bulletRb.mass * speedSqr * direction;
    Destroy(other.gameObject);
    
    rb.AddForce(force,ForceMode.Impulse);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。