Почему мой абордажный пистолет остается прикрепленным, когда я меняю оружие?

#c# #unity3d

Вопрос:

Когда я стреляю из своего абордажного пистолета в поверхность, он работает так, как должен, но когда я переключаюсь на другое оружие, я все еще прикреплен к поверхности, и мне приходится переключаться обратно на абордажный пистолет, чтобы отделиться от поверхности. Кто-нибудь знает, как я мог бы сделать так, чтобы я отстранялся, когда меняюсь оружием?

Вот код переключения оружия:

 using UnityEngine;

public class WeaponSwitching : MonoBehaviour {

   
public int selectedWeapon = 0;

    // Start is called before the first frame update
    void Start()
    {
       SelectWeapon(); 
    }

    // Update is called once per frame
    void Update() {

        int previousSelectedWeapon = selectedWeapon;

        if (Input.GetAxis("Mouse ScrollWheel") > 0f)
        {
            if (selectedWeapon >= transform.childCount - 1)
                selectedWeapon = 0;
            else
                selectedWeapon  ;
        }

        if (Input.GetAxis("Mouse ScrollWheel") < 0f)
        {
            if (selectedWeapon <= 0)
                selectedWeapon = transform.childCount - 1;
            else
                selectedWeapon--;
        }

        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            selectedWeapon = 0;
        }

        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            selectedWeapon = 1;
        }

        if (Input.GetKeyDown(KeyCode.Alpha3) amp;amp; transform.childCount >= 2)
        {
            selectedWeapon = 2;
        }

        if (previousSelectedWeapon != selectedWeapon)
        {
            SelectWeapon();
        }

    }

    void SelectWeapon ()
    {
        int i = 0;
        foreach (Transform weapon in transform)
        {
            if (i == selectedWeapon)
                weapon.gameObject.SetActive(true);
            else
                weapon.gameObject.SetActive(false);
            i  ;
        }
    }
}
 

Вот код оружия для захвата:

 using UnityEngine;

public class GrapplingGun : MonoBehaviour {

    private LineRenderer lr;
    private Vector3 grapplePoint;
    public LayerMask whatIsGrappleable;
    public Transform gunTip, camera, player;
    private float maxDistance = 100f;
    private SpringJoint joint;

    void Awake() {
        lr = GetComponent<LineRenderer>();
    }

    void Update() {
        if (Input.GetMouseButtonDown(0)) {
            StartGrapple();
        }
        else if (Input.GetMouseButtonUp(0))
        {
            StopGrapple();
        }
    }

    void LateUpdate() {
        DrawRope();
    }

    void StartGrapple() {
        RaycastHit hit;
        if (Physics.Raycast(camera.position, camera.forward, out hit, maxDistance, whatIsGrappleable)) {
            grapplePoint = hit.point;
            joint = player.gameObject.AddComponent<SpringJoint>();
            joint.autoConfigureConnectedAnchor = false;
            joint.connectedAnchor = grapplePoint;

            float distanceFromPoint = Vector3.Distance(player.position, grapplePoint);

          
            joint.maxDistance = distanceFromPoint * 0.8f;
            joint.minDistance = distanceFromPoint * 0.25f;

        
            joint.spring = 4.5f;
            joint.damper = 7f;
            joint.massScale = 4.5f;

            lr.positionCount = 2;
            currentGrapplePosition = gunTip.position;
        }
    }


   
    void StopGrapple() {
        lr.positionCount = 0;
        Destroy(joint);
    }

    private Vector3 currentGrapplePosition;
    
    void DrawRope() {
        if (!joint) return;

        currentGrapplePosition = Vector3.Lerp(currentGrapplePosition, grapplePoint, Time.deltaTime * 8f);
        
        lr.SetPosition(0, gunTip.position);
        lr.SetPosition(1, currentGrapplePosition);
    }

    public bool IsGrappling() {
        return joint != null;
    }

    public Vector3 GetGrapplePoint() {
        return grapplePoint;
    }
}
 

Вот код переключения оружия для захвата:

 using UnityEngine;

public class GrappleGunWeaponSwitching : MonoBehaviour
{

    public int selectedWeapon = 0;

    // Start is called before the first frame update
    void Start()
    {
       SelectWeapon(); 
    }

    // Update is called once per frame
    void Update() {

        int previousSelectedWeapon = selectedWeapon;

        if (Input.GetAxis("Mouse ScrollWheel") > 0f)
        {
            if (selectedWeapon >= transform.childCount - 1)
                selectedWeapon = 0;
            else
                selectedWeapon  ;
        }

        if (Input.GetAxis("Mouse ScrollWheel") < 0f)
        {
            if (selectedWeapon <= 0)
                selectedWeapon = transform.childCount - 1;
            else
                selectedWeapon--;
        }

        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            selectedWeapon = 0;
        }

        if (Input.GetKeyDown(KeyCode.Alpha2) amp;amp; transform.childCount >= 2)
        {
            selectedWeapon = 1;
        }

        if (previousSelectedWeapon != selectedWeapon)
        {
            SelectWeapon();
        }

    }

    void SelectWeapon ()
    {
        int i = 0;
        foreach (Transform weapon in transform)
        {
            if (i == selectedWeapon)
                weapon.gameObject.SetActive(true);
            else
                weapon.gameObject.SetActive(false);
            i  ;
        }
    }
}
 

Вот моя иерархия:

иерархия

Спасибо

Комментарии:

1. Чаевые. Вместо этого у вас может быть итерация, которая есть в SelectWeapon, в функции «Пуск», и вы добавляете все игровые объекты в список, поэтому вам нужно просто итератировать по списку. Это может сделать его немного более понятным с точки зрения удобочитаемости.

Ответ №1:

Я думаю GrappleGunWeaponSwitching , что Сценарий несколько избыточен, не так ли?

У меня было бы 2 решения для вас, я думаю. Сначала вы могли бы добавить OnDisable() функцию (событие) в GrapplingGun скрипт и написать что-то вроде этого

 void OnDisable() {
    StopGrapple();
}
 

Проблема в том, что каждый раз, когда вы отключаете скрипт, он также запускается. Но я думаю, что это не будет проблемой.

Другим решением может быть добавление Gun родительского сценария, в котором каждое из ваших орудий является дочерним. Это выглядело бы public class GrapplingGun : Gun { так . Теперь вы сможете изменить эту функцию в WeaponSwitching

     void SelectWeapon () {
        int i = 0;
        foreach (Transform weapon in transform) {
            Gun gun = weapon.gameObject.GetComponent<Gun>();
            if (i == selectedWeapon) {
                gun.EnableEvent();
                weapon.gameObject.SetActive(true);
            } else {
                gun.DisableEvent();
                weapon.gameObject.SetActive(false);
            }
            i  ;
        }
    }
 

Теперь вам просто нужно добавить эти две функции в Gun Родительский класс и перезаписать их в каждом дочернем, чтобы они вызывались там. Я надеюсь, что вы знаете кое-что о Полемике, иначе я могу объяснить вам это.

Комментарии:

1. Второе решение, кстати, более профессиональное.

2. Я использовал первое решение, и оно сработало, большое вам спасибо

3. @Josh_Stigzelius Добро пожаловать 😀 Кстати, вы можете выбрать мой ответ в качестве ответа на свой вопрос, чтобы другие люди не смотрели на это, думая, что им нужно добавить ответ xD

Ответ №2:

Не могли бы вы поделиться скриншотом иерархии ваших объектов?

Похоже, что ваш метод SelectWeapon повторяет преобразования дочернего «оружия», поэтому я предполагаю, что ваши объекты оружия являются дочерними объектами объекта с прикрепленным сценарием переключения оружия… сценарий захвата оружия прикреплен к одному из этих игровых объектов дочернего оружия или он прикреплен к родительскому? Если он подключен к родительскому устройству, то переключение оружия не отключает его.

В любом случае, вы могли бы заставить свой сценарий(ы) переключения оружия запускать метод стоп-захвата в своем сценарии захвата оружия при переключении оружия, что, я думаю, должно сработать? Что-то вроде этого:

 public class WeaponSwitching : MonoBehaviour {


public int selectedWeapon = 0; 
public GrapplingGun grapplingGun; // ADDED

void Start()
{
   grapplingGun = gameObject.GetComponentInChildren<GrapplingGun>(); // ADDED
   SelectWeapon(); 
}
...

    void SelectWeapon ()
    {
        int i = 0;
        foreach (Transform weapon in transform)
        {
            if (i == selectedWeapon)
                weapon.gameObject.SetActive(true);
            else
                weapon.gameObject.SetActive(false);
            i  ;
        }
    if (grapplingGun != null) { grapplingGun.StopGrapple(); } // ADDED
    }
}
 

Вам также нужно будет установить свой метод стоп-захвата на публичное использование.

Если бы вы думали, что столкнетесь с аналогичными проблемами с другим оружием, вы могли бы сделать свои классы оружия производными от мастер-класса оружия и определить различные конкретные результаты для методов с общим названием (например, «Активировать» и «Деактивировать»). Затем вы могли бы просто обработать метод «Деактивировать» на всех дочерних устройствах оружия при каждом изменении оружия.

Комментарии:

1. Добавил ссылку на изображение моей иерархии — большое вам спасибо за помощь