게임/개발

|유니티| 3 | 유저 입력 & 오브젝트 말풍선(텍스트) 띄우기 & 카메라와 마주보는 스프라이트

no title

이전 글 추가 팁

1. 오브젝트를 추적하는 카메라

LookAt(_target _)

카메라가 타겟 오브젝트에 알아서 transform.Roation을 추적한다
단, transform.position만큼은 그대로.

    public Transform target;
    public float dist
    public float height
      
    private Transform tr;
    // Use this for initialization

    void Start()
    {
        tr = GetComponent<Transform>();
    }

    //Update is called once per frame
    void Update()
    {
        //카메라 위치 설정
        tr.position = target.position + (1 * Vector3.right * dist) + (Vector3.up * height);
        //tr.position = target.position + (1 * Vector3.back * dist) + (Vector3.right * dist);
        tr.LookAt(target);
    }

2. 머티리얼 모드 Metallic & Specular Mode

1번이 Metallic Mode. / 2번이 Specular Mode 이다

3. 머티리얼 텍스쳐 늘려짐(Stretched) 타일링으로 해결하자

인스펙터에서 텍스쳐 설정을 수정해보자

User Input

1 입력 Input의 매서드

GetAxis : 화살표 조작 & 마우스 이동량
> 1. GetAxis("Horizontal")

  • 상하
Input.GetAxis("Horizontal")
//output은 
   //오른화살표 : 1
   //왼쪽화살표 : -1 
   //중립 : 0

> 2. GetAxis("Vertical")

  • 좌우
Input.GetAxis("Vertical")
//output은 
   //오른화살표 : 1
   //왼쪽화살표 : -1 

> 3. GetAxis("Mouse X / Mouse Y")

  • 마우스 이동량

GetKey{Down, Up, 없음} : 다양한 키 조작을 입력
> 4. GetKey---()

GetMouse{ButtonDown, ButtonUp, Button} : 마우스 클릭을 입력
> 5. GetMouse---()

  • 다음은 GetMouse의 종류이다
    1. GetMouseDown()
      • 누른 프레임 동안 true를 반환합니다
    2. GetMouseUp()
      • 버튼을를 떼는 즉시 프레임에 true 반환
    3. GetMouse()
      • 눌렸는지 여부에 따라 true 반환
  • 0 : 좌클릭, 1 : 우클릭, 2 : 휠 클릭

Input.mousePosition : 스크린에서 마우스 커서의 위치는?


2 오브젝트 각도 조절

https://blog.naver.com/PostView.nhn?blogId=dj3630&logNo=221447943453

> transform.rotation = Quaternion...

쿼터니언 매개변수를 받는다 Quaternion 이라는 (x,y,z,w) 성분을 이용해 사용한다

tr.rotation = Quaternion.Euler(rotA, curY, curZ);
> transform.loaclEulerAngles = Vector3...

Vector3 매개변수를 받는다

transform.loaclEulerAngles = new Vector(X,Y,Z);

3. 땅 기울이기 코드 & 오브젝트 점프

1. 땅 기울이기 : 키다운
    float curX;float curY;float curZ;
    public Transform tr;
    // Start is called before the first frame update
    void Start()
    {
        tr = GetComponent<Transform>();
        curX = tr.localEulerAngles.x;
        curY = tr.localEulerAngles.y;
        curZ = tr.localEulerAngles.z;
    }

    // Update is called once per frame
    void Update()
    {
        float rotA = tr.localEulerAngles.x;
        rotA += Input.GetAxis("Horizontal");
        tr.rotation = Quaternion.Euler(rotA, curY, curZ);
    }
1. 땅 기울이기 : 마우스 클릭
if(Input.touchCount > 0 || Input.GetMouseButton(0)){
    //게임 화면 스크린을 반띵해서 오른쪽 왼쪽 클릭을하면 반응
    if(Input.mousePosition.x < Screen.width / 2f){
        tr.rotation = Quaternion.Euler(tr.localEulerAngles.x-1, curY, curZ);
    }
    else if (Input.mousePosition.x >= Screen.width / 2f){
        tr.rotation = Quaternion.Euler(tr.localEulerAngles.x+1, curY, curZ);
    }
}
결과물
Scene Game
2. 오브젝트 점프
 void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space) == true){
            GetComponent<Rigidbody>().AddForce(Vector3.up * 300);
        }
    }
결과물

오브젝트에 말풍선 달기

사실 점프하는걸 구현은 했는데
내가 진짜로 점프했는지 시각적으로 표시하면 좋겠다 생각했다

그래서 생각한절차는 다음과 같다.

1. 텍스트는?

1. 점프(space)를 할때 같이 텍스트도 반응하면 좋지 않을까?
    * 상자나 원통, 구 같은 3D 오브젝트는 알겠는데..
    * 그런데 유니티에서는 텍스트라는것은 어떻게 표현하는거지?
        Hierarchy(우클릭) -> Create -> 3D Object - Text(TextMashPro) 
Scene Game

2. 오브젝트의 부모와 자식

2. 아 ㅇㅋ 텍스트는 어떻게 꺼내는지는 알겠어 공위에 텍스트를 띄우면 된다
    * 근데 공이랑 텍스트랑 나름 연관/상관관계는 있어야 하는거 아닌가?
    * 공이랑 텍스트랑 연관짓고싶은데 어떻게 해야할까?


  1. Ball_Group은 하위 오브젝트(Ball, Text) 입장에서 Parent 가 되겠다.
  2. Ball, Text는 Ball_Group의 Child가 되겠다.
사용처는 다음과 같다 부모의 Transform 전~부를 모방하도록 하고싶다.

단, 글로벌 포지션이랑 로컬 포지션을 잘 구분해야지 아다리가 잘 맞는다.
transform.position 대신 transform.localPosition 을 이용하자

랜덤 시스템

  public float cylPos = 0.0f; 
    public float cylSpeed = 0.05f;
    float delta;
    float cylX;
    float cylY;
    float nextZ;
    int[] NePoArr = {-1,1};
    // Start is called before the first frame update
    void Start()
    {
        cylX = transform.localPosition.x;
        cylY = transform.localPosition.y;
        cylPos = UnityEngine.Random.Range(-0.47f, 0.47f);
        nextZ = transform.localPosition.z + cylPos;
        System.Random rand = new System.Random();
        int randomIndex = rand.Next(0,1);
        delta = (float)NePoArr[randomIndex] * cylSpeed;
        this.transform.localPosition = new Vector3(cylX, cylY,nextZ);
    }

    // Update is called once per frame
   void Update()
    {
        if(transform.localPosition.z < -0.47f){
            delta = 1f * cylSpeed;
        }
        else if(transform.localPosition.z > 0.47f){
            delta = -1f * cylSpeed;
        }
        nextZ = transform.localPosition.z + delta;
        this.transform.localPosition = new Vector3(cylX, cylY, nextZ);
    }

3. ball의 위치를 모방하는 Text

3. 당연히 ball의 position을 가져오기만하면 Text의 위치선정을 할수 있을것이다.
//스크립트 파일이름은 TracingText.cs 이다.

public GameObject G; //G는 인스펙터 창에서 공(Ball) 게임 오브젝트를 가져오면 된다
void Update()
{
    transform.position = new Vector3(
        G.transform.position.x,
        G.transform.position.y,
        G.transform.position.z
    );//다음은 타겟 오브젝트 Ball을 G로 받은다음 Position 붙여놓는것이다.
}

4. 작동할때만 보여주고 아닐땐 숨기자.

4. 텍스트가 보여진다는것의 의미는 어떻게 보면 있었는데 없던거다
    * 그렇다면 다음과 같이 생각할수 있지 않나?
        * 보여진다 -> ON : gameObject.SetActive(true)
        * 안보인다 -> OFF : gameObject.SetActive(false)
    * 평상시에는 OFF 하다가 이벤트 오면 ON 하면 되겠네.. ㅋㅋ

5. 몇초 유지할래? yield return new WaitForSeconds(_Time _)

5. 아까 말했듯 공이 점프할때 썼던 Input.GetKeyDown(Keycode.Space) 을 쓰면 좋겠다 
    * 근데 GetKeyDown만 하면 정확히 60중에 1프레임에 "깜빡" 보여질것이다.
        * 깜빡이 아닌 지속적인 신호를 보내는것은 GetKey() 인데..
        * 솔찍히 점프는 적어도 길게 누르라고 있는건 아니다.
    * 깜빡 하는거 보려고 이거 시작한게 아니다. "클릭" 하고 적어도 1~2초 정도는 유지하면 좋지 않을까?
참고한 블로그는 다음과 같다
  1. https://guks-blog.tistory.com/entry/Unity-부모-오브젝트-자식-오브젝트-가져오기Script

  2. https://neojsm.tistory.com/13

//스크립트 파일이름은 TextJumpingAct.cs 이다.
    public float exposeTime; //인스펙터 창에서 직접 시간을 정해줄 수 있다.
    
    void Start()
    {
        transform.GetChild(1).gameObject.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space) == true){
           StartCoroutine(DrawText());
        }
    }
    IEnumerator DrawText()
    {
        transform.GetChild(1).gameObject.SetActive(true);
        yield return new WaitForSeconds(exposeTime);
        transform.GetChild(1).gameObject.SetActive(false);
    }

카메라를 마주보는 텍스트.. Facing

점프할때마다 텍스트 띄우는건 했다
하지만 텍스트의 각도를 수정하지않으면 정작
게임 카메라에는 보이지 않거나 애매하게 이상하게 띄워지는 경우가 있다.

1. 일일이 각도수정? 다양한 상황에 대처하자

1. 어디서 바라보든 Text가 마주볼 수는 없나 생각했다.
    * 다음은 스프라이트와 3D를 적절히 사용해 메모리를 아낀 게임이다
        * 슈퍼마리오 64 나무
        * 둠 몬스터
슈퍼마리오

2. Facing Camera

2. 포럼에서 찾았다.

https://answers.unity.com/questions/1420878/how-to-make-a-floating-text-over-an-object-that-al.html

3. 결과 : 카메라 각도에 상관없이 잘보임

3.Text의 Y각도에 따라 Mathf.Cos() / Mathf.Sin() 을 지정해줘서 좀더 공의 위치에 착 들어맞게 코드는 손봤다
    public Camera cameraToLookAt;
    public GameObject G;
    // Start is called before the first frame update
    void Start()
    {
        cameraToLookAt = Camera.main;
    }

    // Update is called once per frame
    void Update()
    {
        transform.position = new Vector3(
            G.transform.position.x + (8.5f *Mathf.Sin(cameraToLookAt.transform.localEulerAngles.y)),
            G.transform.position.y,
            G.transform.position.z + (8.5f *Mathf.Cos(cameraToLookAt.transform.localEulerAngles.y))
        );
    }
    public Camera cameraToLookAt;
 
     // Use this for initialization 
     void Start()
     {
         cameraToLookAt = Camera.main;
     }
 
     // Update is called once per frame 
     void LateUpdate()
     {
         transform.LookAt(cameraToLookAt.transform);
         transform.rotation = Quaternion.LookRotation(cameraToLookAt.transform.forward);
     }
정면뷰 다른각도