[Cyphers] 에임 - CrossHair 생성, 마우스에 따른 캐릭터 회전
2023. 9. 26.

논타겟팅 게임의 에임

 

-사이퍼즈는 논타겟팅 게임이다. 논타겟팅 게임이란 공격을 누구한테 할지, 타겟을 정하지 않고도 때렸더니 맞았다면 공격이 되는 게임이다. 즉 이펙트가 어떻게 날아가고 부딪히냐에 따라 맞을수

도 맞지않을 수도 있는 것이다.

 

 

https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Mouse.html

 

Mouse support | Input System | 1.0.2

Mouse support The Input System represents mouse input with the Mouse Device layout that the Mouse class implements. Mice are based on the Pointer layout. To query the last used or last added mouse, use Mouse.current. var mouse = Mouse.current; Note: The In

docs.unity3d.com

사이퍼즈에서 마우스는 여러 역할을 한다.

-첫째, 플레이어는 마우스를 통해 시점을 이동할 수 있다. 왼쪽으로 마우스를 움직이면 플레이어의 시점이 왼쪽으로 가고, 오른쪽으로 움직이면 오른쪽으로 시점이 이동한다.

- 둘째, 에임을 맞춰, 스킬 입력이 있으면 공격한다. 

 

에임 생성

-먼저 마우스의 에임을 만들어주려한다. 

-사이퍼즈의 에임은 정중앙에서 고정되어있지 않다. 마우스의 움직임에 따라 위치가 변하며, 에임에 오브젝트가 감지되면 파란색이되며 사이즈가 줄어든다.

- 움직이는 에임이지만 최고 위치, 최저 위치가 있다.

상,하 움직임/ 대각선으로 에임 돌렸을때의 카메라 회전

https://docs.unity3d.com/ScriptReference/Cursor.SetCursor.html

 

Unity - Scripting API: Cursor.SetCursor

texture The texture to use for the cursor. To use a texture, import it with `Read/Write` enabled. Alternatively, you can use the default cursor import setting. If you created your cursor texture from code, it must be in RGBA32 format, have alphaIsTranspare

docs.unity3d.com

-에임의 이미지를 바꿔주기 위해 Cursor.SetCursor를 사용했다.

-texture type이 Cursor로 되어있어야한다.

커서 이미지 변경 - ChangeMouseMode()

기존의 플레이어의 Rotation을 없애주고, 마우스의 위치에 따라 회전하도록 코드를 수정하였다.

 

MouseController / ClareController

-MouseController의 GetMouseScreenPosition에서 마우스의 현재 위치를 받는다. 

-MouseLook 메서드에서 이를 그냥 호출하게 되면 값이 변하지 않더라도 멤버변수에 저장할 수 있으므로, 기존 멤버변수의 값과 새로운 GetMouseScreenposition 값을 비교해 다른 경우에만 멤버변수에 저장하도록하였다.(37라인)

-마우스를 오른쪽으로 움직였는지 왼쪽으로 움직였는지를 알기 위해 어떤 값이 큰지 비교하였다. 기존에 멤버 변수 값이 크다면 새로 입력된 값이 더 작은 것이므로 왼쪽이다.

 

 

커서이미지 변경, 마우스 커서의 이동에 따른 회전구현

-다시 게임을 확인해보니 에임의 방향에 따라 카메라가 그 방향을 바라본다. 수정이 필요하다.

-현재에는 마우스 커서의 위치가 화면의 어디든지 갈 수 있다. 그러나 사이퍼즈의 에임은 가운데의 일정 범위 내에서만 상하로 움직인다. 커서의 이미지를 투명한 것으로 바꾸고 일정 범위 내에서만 crossHair를 움직이도록 수정하자.

커서를 투명하게 변경

-일정범위 내에서 crossHair는 커서의 위치(y축)를 받는다. 에임은 상,하로 움직인다.

-마우스의 위치를 받아 회전 시켜주되, 최대 회전 각도를 제한한다. 제한하지 않으면 360도로 회전할 수 있기 때문이다.

 

 

마우스 이동에 따른 회전 구현 수정 후

 

 

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
public class MouseController : MonoBehaviour
{
    [SerializeField] GameObject cameraGo;
    [SerializeField] private Image aimImage;
    [SerializeField] private Texture2D cursorTexture;
    private CursorMode cursorMode = CursorMode.Auto;
    private Vector2 hotSpot = Vector2.zero;
    private Vector3 mousePosHorizontal;
    private Vector3 mousePosVertical;

    // Start is called before the first frame update
    void Start()
    {
        //set image on center
        this.hotSpot.x = cursorTexture.width / 2;
        this.hotSpot.y = cursorTexture.height / 2;

    }

    // Update is called once per frame
    void FixedUpdate()
    {
        Cursor.lockState = CursorLockMode.Confined;

        this.ChangeMouseMode();
        this.MouseLook();
        this.MouseVertical();
        //  Debug.Log(this.cameraGo.transform.rotation.eulerAngles);
        var layerMask = 3 << LayerMask.NameToLayer("Tower");
        //  Vector3 rayPos = new Vector3(this.cameraGo.)
        Transform rayTrans = this.aimImage.transform;
        Ray ray = new Ray(rayTrans.position, cameraGo.transform.forward);
        //  Ray ray = new Ray(this.aimImage.rectTransform.anchoredPosition, this.cameraGo.transform.forward);
        Debug.DrawRay(ray.origin, ray.direction * 10f, Color.red, 0.5f);
        RaycastHit hit;

        if (Physics.Raycast(ray.origin, ray.direction, out hit, 10.0f, layerMask))
        {
            Debug.Log(hit.collider.gameObject);
        }
    }


    private void ChangeMouseMode()
    {

        Cursor.SetCursor(cursorTexture, hotSpot, cursorMode);
    }
    private void MouseLook()
    {

        Vector3 mousePos = GetMouseScreenPosition();
        this.aimImage.rectTransform.anchoredPosition = new Vector3(0, mousePos.y * 0.4f - 80, 0);
        // if (this.mousePosHorizontal != GetMouseScreenPosition())
        {


            if (this.mousePosHorizontal.x > GetMouseScreenPosition().x)
            {//마우스를 왼쪽으로 움직이는 경우
                this.mousePosHorizontal = GetMouseScreenPosition();
                this.transform.Rotate(Vector3.up * -150f * Time.deltaTime);//좌우는 몸이 통째로 돌아간다.
               // this.cameraGo.transform.LookAt(this.transform.position);
             //  this.cameraGo.transform.Rotate(Vector3.up * -150f * Time.deltaTime);
            }
            else if (this.mousePosHorizontal.x <GetMouseScreenPosition().x)
            {//마우스를 오른쪽으로 움직이는 경우
                this.mousePosHorizontal = GetMouseScreenPosition();
                this.transform.Rotate(Vector3.up * 150f * Time.deltaTime);//좌우는 몸이 통째로 돌아간다.
                                                                          //  this.cameraGo.transform.LookAt(this.transform.position);
              //  this.cameraGo.transform.Rotate(Vector3.up * 150f * Time.deltaTime);
            }
            else
            {
                this.mousePosHorizontal = GetMouseScreenPosition();
            }


        }




    }
    private void MouseVertical()
    {
        float vertical = this.mousePosVertical.y - GetMouseScreenPosition().y;
        //Debug.Log(vertical);

        if (vertical != 0)
        {

            // Debug.Log(GetMouseScreenPosition().y);
            if (vertical <= 0)
            {
                float rotationValue = 0;
                //  Debug.LogFormat("Up: {0} ", GetMouseScreenPosition().y - this.mousePosVertical.y);
                this.mousePosVertical = GetMouseScreenPosition();              
                rotationValue = -this.mousePosVertical.magnitude * 0.04f * Time.deltaTime;
                if (345 < this.cameraGo.transform.eulerAngles.x && this.cameraGo.transform.eulerAngles.x < 360)               
                {
                    this.cameraGo.transform.Rotate(Vector3.right * rotationValue);
                }
                else if (this.cameraGo.transform.eulerAngles.x < 20f)
                {
                    this.cameraGo.transform.Rotate(Vector3.right * rotationValue);
                }
                else
                {
                    //   Debug.Log("maximum");
                }
                //   this.cameraGo.transform.rotation = Quaternion.Euler(Vector3.right*rotationValue*10f);
            }
            else if (vertical>0)
            {
                //Debug.LogFormat("Down: {0} ", this.mousePosVertical.y - GetMouseScreenPosition().y);
                float rotationValue = 0;
                this.mousePosVertical = GetMouseScreenPosition();
                //rotationValue = this.mousePosVertical.y * 0.07f * Time.deltaTime;
                rotationValue = this.mousePosVertical.magnitude * 0.04f * Time.deltaTime;
                //if (this.cameraGo.transform.rotation.x < 0.04)
                if (this.cameraGo.transform.eulerAngles.x < 360f && this.cameraGo.transform.eulerAngles.x > 50)
                {
                    this.cameraGo.transform.Rotate(Vector3.right * rotationValue);
                }
                //  this.cameraGo.transform.rotation = Quaternion.Euler(Vector3.right * rotationValue * -10f);

            }
        }
    }

    private Vector3 GetMouseScreenPosition()
    {

        return Mouse.current.position.ReadValue();//mouse position
    }
}
myoskin