[Unity]タグティン・ローウェン


トランスフォーマー


前の記事で敵にマウスを置いたとき、いつもと違うカーソルを表示するように設定しました.今期の文章は敵をクリックする際の行動を規定している.
初めて地面をクリックし、マウスを押した状態でポインタを移動すると、キャラクターはポインタに従って移動します.しかし、初めて敵をクリックすると、マウスを押してポインタを動かしても、プレイヤーは敵のところに行きたいと思っています.そのためには、まずコードを修正する必要があります.
public enum MouseEvent
{
    Press,
    PointerDown,
    PointerUp,
    Click,
}
DefineクラスのMouseEvent Enumは元々PressとClickのみで、最初にクリックしたオブジェクトが何であるかを判別するためにPointerDownとPointerUpの2つの状態が追加されています.
public void OnUpdate()
{
    if (EventSystem.current.IsPointerOverGameObject())
        return;

    if (Input.anyKey && KeyAction != null)
        KeyAction.Invoke();

    if (MouseAction != null)
    {
        if (Input.GetMouseButton(0))
        {
            if(!_pressed)
            {
                MouseAction.Invoke(Define.MouseEvent.PointerDown);
                _pressedTime = Time.time;
            } // 신규 작성 코드
            MouseAction.Invoke(Define.MouseEvent.Press);
            _pressed = true;
        }
        else
        {
            if (_pressed)
            {
                if (Time.time < _pressedTime + 0.2f)
                    MouseAction.Invoke(Define.MouseEvent.Click); // 신규 작성 코드
                MouseAction.Invoke(Define.MouseEvent.PointerUp);
            }
            _pressedTime = 0; // 신규 작성 코드
            _pressed = false;
        }
    }
}
InputManagerクラスのOnUpdate()関数を変更しました.
従来と異なり、Invoke PointerDownとUpのコードが追加された.
上記の場合、1回目のクリック時にPointerDownがInvokeされてマウスが押された時間を測定します.同時にPressを覚えて、後でPressだけを覚えます.
マウスを押さない場合は、まず上でマウスを押す時間が0.2秒未満であれば、Inovke Click、そうでなければInovke PointerUpになります.
int _mask = (1 << (int)Define.Layer.Ground) | (1 << (int)Define.Layer.Monster);
GameObject _lockTarget;
void OnMouseEvent(Define.MouseEvent evt)
{
    if (_state == PlayerState.Die)
        return;

    RaycastHit hit;
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    bool raycastHit = Physics.Raycast(ray, out hit, 100.0f, _mask);

    switch (evt)
    {
        case Define.MouseEvent.PointerDown:
            {
                if (raycastHit)
                {
                    _destPos = hit.point;
                    _state = PlayerState.Moving;

                    if (hit.collider.gameObject.layer == (int)Define.Layer.Monster)
                    {
                        _lockTarget = hit.collider.gameObject;
                    }
                    else
                    {
                        _lockTarget = null;
                    }
                }
            }
            break;
        case Define.MouseEvent.Press:
            {
                if (_lockTarget != null)
                    _destPos = _lockTarget.transform.position;
                else if (raycastHit)
                    _destPos = hit.point;
            }
            break;
        case Define.MouseEvent.PointerUp:
            _lockTarget = null;
            break;
    }
}
Player Controlのコードを変更しました.switch文を使用して、マウスイベントに基づいて動作を区別します.
lockTargetという変数を追加し、最初にクリックしたオブジェクトが敵の場合はlockTarget変数に敵を格納します.その後、Pressアクティビティを受信するたびにlockTargetが判別され、lockTargetがNullであればマウスを押した場所に移動し、lockTargetがあれば無条件にlockTargetに移動する.
コードを変更した後、予定通りに動作することを確認します.ただし、初めて地面をクリックして移動するときに、マウスを敵にぶら下げるとカーソルが変わり、修正が必要になります.
void UpadateMouseCursor()
{
    if (Input.GetMouseButton(0))
        return;
        ...
}            
Player ControlのUpdateMouseCursor()関数を変更しました.単純にマウスを押すと関数が戻るという問題を解決しました.予定通りに動作していることを確認します.