Дублированные объекты не работают "на экземпляр", когда я намеревался их делать

using UnityEngine;

public class LinkEnd : MonoBehaviour
{
    public GameObject linkTarget;
    private PointEffector2D effector;
    private CircleCollider2D contact;
    private AimSystem aimer;

    private float distFromLink = .2f;
    public bool connected;

    private void Start()
    {
        aimer = GetComponent<AimSystem>();
    }

    private void Update()
    {
        SyncPosition();

        ReactToInput();
    }

    public void ConnectLinkEnd(Rigidbody2D endRB)
    {
        HingeJoint2D joint = GetComponent<HingeJoint2D>();

        if (GetComponent<HingeJoint2D>() == null)
        {
            joint = gameObject.AddComponent<HingeJoint2D>();
        }

        joint.autoConfigureConnectedAnchor = false;
        joint.connectedBody = endRB;
        joint.anchor = Vector2.zero;
        joint.connectedAnchor = new Vector2(0f, -distFromLink);
    }

    private void SyncPosition()
    {
        if (linkTarget != null)
        {
            if (Vector2.Distance(transform.position, contact.transform.position) <= 0.1f)
            {
                connected = true;
                effector.enabled = false;
                contact.usedByEffector = false;
            } 
        }

        if (connected)
        {
            GetComponent<Rigidbody2D>().isKinematic = true;
            GetComponent<Rigidbody2D>().position = linkTarget.transform.position;
        }
        else
            GetComponent<Rigidbody2D>().isKinematic = false;
    }

    private void ReactToInput()
    {
        if (Input.GetKeyUp(KeyCode.Mouse0) || Input.GetKey(KeyCode.Mouse1))
        {
            connected = false;
        }
    }

    public void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.GetComponent<PointEffector2D>() != null)
        {
            connected = true;
            linkTarget = collision.gameObject;
            effector = linkTarget.GetComponent<PointEffector2D>();
            contact = linkTarget.GetComponent<CircleCollider2D>();
        }
    }

    public void OnTriggerExit2D(Collider2D collision)
    {
        connected = false;
        contact.usedByEffector = true;
        effector.enabled = true;
    }
}

Это объект, который при столкновении привязывает свою позицию к другому мобильному объекту, и он должен оставаться таким до тех пор, пока не будет "отсоединен" действием игрока. Это работает почти нормально, но это не работает "на экземпляр". Является ли этот объект сборным или нет, ReactToInput() влияет на все его экземпляры в отличие от того, что я хотел. Мне не хватает некоторых спецификаций здесь, и я не вижу, где.

Любое предложение поможет и будет оценено!

++ Метод ReactToInput () запускается с помощью ключевых вводов. Я хотел, чтобы этот метод вызывался, когда происходит "метод" атаки Player, связанный с этими ключевыми входами, но я сделал то, что сделал, только потому, что не смог найти элегантный способ выполнить его иначе, и я действительно надеюсь, что есть лучший способ, чем использовать теги или GetComponent для конкретного объекта, поскольку он также влияет на другие объекты.

1 ответ

Эти методы - то, что вы ищете.

/// <summary>
/// OnMouseDown is called when the user has pressed the mouse button while
/// over the GUIElement or Collider.
/// </summary>
void OnMouseDown()
{
    Debug.Log("Hi!");

}

/// <summary>
/// OnMouseUp is called when the user has released the mouse button.
/// </summary>
void OnMouseUp()
{
    Debug.Log("Bye!");
}

MonoBehaviour обеспечивает много обратных вызовов событий, кроме Update()и эти двое являются одними из них. Полный список обратных вызовов событий, которые вы можете использовать для MonoBehaviour объясняется на официальной странице Monobehaviour.

Есть два метода для OnMouseUp():

OnMouseUp вызывается, когда пользователь отпустил кнопку мыши.

OnMouseUpAsButton вызывается только тогда, когда мышь отпущена над тем же элементом GUIElement или Collider, который был нажат.

GameObject Ваш сценарий, к которому прикреплен, требует использования GUIElement или Collider, как описано на странице руководства, чтобы использовать эти функции.

Если вы не хотите использовать эти методы, вы можете написать свой собственный InputModule, raycast в положение мыши на экране, чтобы найти, какой объект нажал, и отправить MouseButtonDown() событие для клика GameObject,

Я должен был реализовать пользовательский модуль ввода, чтобы сделать это, плюс пару других вещей, и я уверяю вас, что вы пишете пользовательские InputModuleэто головная боль


РЕДАКТИРОВАТЬ:

Если много разных классов должны быть уведомлены, когда что-то происходит, и кто слушает такие случаи, неизвестно, event хороший вариант

Если вы используете eventsкаждый класс слушателя событий, такой как LinkEnd несет ответственность за регистрацию и удаление себя на такое событие.

Ниже приведен пример того, как вы могли бы достичь этого поведения:

class Player
{
    public delegate void OnSkillAFiredListener(object obj, SkillAFiredEventArgs args);
    public static event OnSkillAFiredListener SkillAPressed = delegate { };
    // ...
}

class LinkEnd
{
    void OnEnable()
    {
        Player.SkillAPressed += WhatToDoWhenSkillAFired;
    }

    void OnDisable()
    {
        Player.SkillAPressed -= WhatToDoWhenSkillAFired;
    }

    void OnDestroy()
    {
        Player.SkillAPressed -= WhatToDoWhenSkillAFired;
    }

    public void WhatToDoWhenSkillAFired(object obj, SkillAFiredEventArgs args)
    {
        // get info from args
        float someInfo = args.someInfo

        // do something..
        Bark();
    }

    // ...
}

Необходимо отменить регистрацию от события в обоих OnDisable() а также OnDestory() чтобы избежать утечек памяти (некоторые утверждают, что такие утечки памяти очень незначительны).

Ищите шаблон Observer и Publisher/Subscriber, чтобы узнать больше об этих подходах. Возможно, это не очень связано с вашим делом, но шаблон посредника часто сравнивают с шаблоном наблюдателя, поэтому вам может быть интересно его проверить.

Другие вопросы по тегам