using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tank : MonoBehaviour
{
    public enum Mode
    {
        TankMode,
        SiegeMode
    }
    void Start()
    {
        
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(1))
        {
            Vector3 mousePosScreen = Input.mousePosition;
            Debug.Log(mousePosScreen); // 캔버스의 크기는 좌측하단 0*0 부터 1920 * 1080이지만 추가로 월드좌표가찍힘
            
        }
    }
}

 

이렇게 하면 Local position의 좌표가 찍히는데 이를 월드좌표로 바꿔줄 것이다.

 

월드 좌표로 바꾸어 보았다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tank : MonoBehaviour
{
    public enum Mode
    {
        TankMode,
        SiegeMode
    }
    void Start()
    {
        
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(1))
        {
            Vector3 mousePosScreen = Input.mousePosition;
            //Debug.Log(mousePosScreen); // 캔버스의 크기는 좌측하단 0*0 부터 1920 * 1080이지만 추가로 월드좌표가찍힘
            Vector2 mousePosWorld = Camera.main.ScreenToWorldPoint(mousePosScreen);
            Debug.Log(mousePosWorld); // (0.00, 1,00)
        }
    }
}

좌하단 -> 중앙 -> 오른쪽위 순으로 나온 좌표이고

 

탱크의 위치는 0,0,0 으로 초기화

 

카메라는 탱크의 위치에 따라가게 Ctrl + Shift + F로 지정하였다.

 

탱크를 클릭한 위치로 이동하게 하였다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tank : MonoBehaviour
{
    public float Speed = 3f;
    public enum Mode
    {
        TankMode,
        SiegeMode
    }
    void Start()
    {
        
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Vector3 mousePosScreen = Input.mousePosition;
            //Debug.Log(mousePosScreen); // 캔버스의 크기는 좌측하단 0*0 부터 1920 * 1080이지만 추가로 월드좌표가찍힘
            Vector2 mousePosWorld = Camera.main.ScreenToWorldPoint(mousePosScreen);
            Debug.Log(mousePosWorld); // (0.00, 1,00)
        }
        if (Input.GetMouseButton(1))
        {
            Vector3 mousePosScreen = Input.mousePosition;
            Vector2 mousePosWorld = Camera.main.ScreenToWorldPoint(mousePosScreen);
            this.transform.position = Vector3.MoveTowards(this.transform.position, mousePosWorld, Speed * Time.deltaTime);
        }


    }
}

 

  • this.transform.position: 현재 객체(탱크)의 위치를 나타냅니다.
  • mousePosWorld: 마우스의 현재 위치를 나타냅니다.
  • Speed * Time.deltaTime: 탱크가 이동할 속도를 결정합니다. Time.deltaTime은 이전 프레임부터 현재 프레임까지의 경과 시간을 나타내며, 이를 사용하여 프레임 레이트에 관계없이 일정한 속도로 이동할 수 있습니다.

 

스타크래프트 마우스를 클릭하고 있어야 되는 것이 아닌 한번 누르면 이동해야 하고 중간에 경로를 변경할 수 있어야 한다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tank : MonoBehaviour
{
    public float Speed = 3f;
    public Vector3 targetPosition = Vector3.zero; // 클릭한 위치를 저장할 변수

    void Update()
    {
        if (Input.GetMouseButtonDown(1)) // 오른쪽 마우스 버튼을 클릭했을 때
        {
            // 마우스 클릭한 위치를 저장
            Vector3 mousePosScreen = Input.mousePosition;
            targetPosition = Camera.main.ScreenToWorldPoint(mousePosScreen);
            //targetPosition.z = 0f; // 2D 게임에서 z 축 값은 0으로 고정
            Debug.Log("New target position: " + targetPosition);
        }

        // 탱크가 저장된 위치로 이동
        if (targetPosition != Vector3.zero)
        {
            transform.position = Vector3.MoveTowards(transform.position, targetPosition, Speed * Time.deltaTime);

            // 탱크가 목표 위치에 도달하면 저장된 위치 초기화
            if (this.transform.position == targetPosition)
            {
                targetPosition = Vector3.zero;
            }
        }
    }
}

 

타켓(클릭된)좌표의 벡터를 0으로 초기화 => Vector3.zero

이동좌표를 정할 때

 

나중에 코드가 길어지면 업데이트에서 처리할일이 많아서 느려질 수 있으므로 코루틴을 사용했다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tank : MonoBehaviour
{
    public float Speed = 3f;
    public Vector3 targetPosition = Vector3.zero; // 클릭한 위치를 저장할 변수

    private void Start()
    {

    }

    void Update()
    {
        if (Input.GetMouseButtonDown(1)) // 오른쪽 마우스 버튼을 클릭했을 때
        {
            StartCoroutine(CoMove()); // 코루틴을 실행합니다.
        }
    }
    IEnumerator CoMove()
    {
        // 마우스 클릭한 위치를 저장
        Vector3 mousePosScreen = Input.mousePosition;
        targetPosition = Camera.main.ScreenToWorldPoint(mousePosScreen);
        //targetPosition.z = 0f; // 2D 게임에서 z 축 값은 0으로 고정
        Debug.Log("New target position: " + targetPosition);
        // 탱크가 저장된 위치로 이동
        while ((targetPosition != Vector3.zero))
        {
            transform.position = Vector3.MoveTowards(transform.position, targetPosition, Speed * Time.deltaTime);

            // 탱크가 목표 위치에 도달하면 저장된 위치 초기화
            if (this.transform.position == targetPosition)
            {
                targetPosition = Vector3.zero;
            }
            yield return null;
        }
    }

}

 

하지만 실행을 해보니 클릭을 할 수록 빨라졌고 코루틴을 중지하는 것이 필요하다고 판단하였다.

 

멤버변수에 현재 실행중인 코루틴을 저장하기 위해 선언하였고

코루틴안에서 실행중이면 정지하도록 하고

다시 코루틴을 시작하게 하였다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tank : MonoBehaviour
{
    public float Speed = 3f;
    public Vector3 targetPosition = Vector3.zero; // 클릭한 위치를 저장할 변수
    private Coroutine moveCoroutine; // 현재 실행 중인 코루틴을 저장하기 위한 변수
    private void Start()
    {

    }

    void Update()
    {
        if (Input.GetMouseButtonDown(1)) // 오른쪽 마우스 버튼을 클릭했을 때
        {
            // 기존에 실행 중인 코루틴이 있으면 중지시킴
            if (moveCoroutine != null)
            {
                StopCoroutine(moveCoroutine);
            }
            // 새로운 코루틴 시작
            moveCoroutine = StartCoroutine(CoMove()); // 코루틴을 실행합니다.
        }
    }
    IEnumerator CoMove()
    {
        // 마우스 클릭한 위치를 저장
        Vector3 mousePosScreen = Input.mousePosition;
        targetPosition = Camera.main.ScreenToWorldPoint(mousePosScreen);
        //targetPosition.z = 0f; // 2D 게임에서 z 축 값은 0으로 고정
        Debug.Log("New target position: " + targetPosition);

        // 탱크가 저장된 위치로 이동
        while ((targetPosition != Vector3.zero))
        {
            transform.position = Vector3.MoveTowards(transform.position, targetPosition, Speed * Time.deltaTime);

            // 탱크가 목표 위치에 도달하면 저장된 위치 초기화
            if (this.transform.position == targetPosition)
            {
                targetPosition = Vector3.zero;
            }
            yield return null;
        }
    }

}

 

 

코드를 수정하기 전에도 있었던 문제 같은데 위치에 도달하면 Tank가 사라지는 것을 발견

 

scene에는 있는데 game scene에서 사라지는 이유를 찾다가

layer in order로 맵뒤에 있는건 아닌지 확인도 하였지만

알고보니, 2D인데 클릭한 좌표가 z축이 입력되서 카메라 시점이 같이 움직였기에 시야 밖에서 사라진 것이었다.

z좌표를 0 으로 초기화하는 변수를 지정하고 인자로 넣어주었더니 문제 없이 실행되었다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tank : MonoBehaviour
{
    public float Speed = 3f;
    private Vector3 targetPosition = Vector3.zero; // 클릭한 위치를 저장할 변수
    private Coroutine moveCoroutine; // 현재 실행 중인 코루틴을 저장하기 위한 변수

    void Update()
    {
        if (Input.GetMouseButtonDown(1)) // 오른쪽 마우스 버튼을 클릭했을 때
        {
            // 기존에 실행 중인 코루틴이 있으면 중지시킴
            if (moveCoroutine != null)
            {
                StopCoroutine(moveCoroutine);
            }



            // 새로운 코루틴 시작
            moveCoroutine = StartCoroutine(CoMove()); // 코루틴을 실행합니다.
        }
    }

    IEnumerator CoMove()
    {
        // 마우스 클릭한 위치를 저장
        Vector3 mousePosScreen = Input.mousePosition;
        targetPosition = Camera.main.ScreenToWorldPoint(mousePosScreen);
        Debug.Log("New target position: " + targetPosition);

        // 탱크가 저장된 위치로 이동
        while (Vector3.Distance(transform.position, targetPosition) > 0.01f)
        {
            Vector3 movePos = new Vector3(targetPosition.x, targetPosition.y, 0);
            transform.position = Vector3.MoveTowards(transform.position, movePos, Speed * Time.deltaTime);
            yield return null;
        }

        // 탱크가 목표 위치에 도달하면 저장된 위치 초기화
        targetPosition = Vector3.zero;
    }
}

 

 

더 해야할 부분 : 

아직 미완성인 부분 o버튼 누를경우 이미지 시즈모드로 변경 다시 o누르면 탱크모드

+ 이동중에 o를 누르면 그 자리에서 즉시 이미지 변경

 

우선 O키를 눌러서 콘솔에 찍어보았고

움직이는 중간에 계속 콘솔에 찍혔다.

이 점에 대해 구현을 한다면 O를 누르면 시즈모드가 멈추고 이미지가 변경 되어야 할 것이다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tank : MonoBehaviour
{
    public float Speed = 3f;
    private Vector3 targetPosition = Vector3.zero; // 클릭한 위치를 저장할 변수
    private Coroutine moveCoroutine; // 현재 실행 중인 코루틴을 저장하기 위한 변수

    void Update()
    {
        if (Input.GetMouseButtonDown(1)) // 오른쪽 마우스 버튼을 클릭했을 때
        {
            // 기존에 실행 중인 코루틴이 있으면 중지시킴
            if (moveCoroutine != null)
            {
                StopCoroutine(moveCoroutine);
            }
            // 새로운 코루틴 시작
            moveCoroutine = StartCoroutine(CoMove()); // 코루틴을 실행합니다.
            
        }
        if (Input.GetKeyDown(KeyCode.O))
        {
            Debug.Log("시즈모드 전환");
        }
    }

    IEnumerator CoMove()
    {
        // 마우스 클릭한 위치를 저장
        Vector3 mousePosScreen = Input.mousePosition;
        targetPosition = Camera.main.ScreenToWorldPoint(mousePosScreen);
        Debug.Log("New target position: " + targetPosition);

        // 탱크가 저장된 위치로 이동
        while (Vector3.Distance(transform.position, targetPosition) > 0.01f)
        {
            Vector3 movePos = new Vector3(targetPosition.x, targetPosition.y, 0);
            transform.position = Vector3.MoveTowards(transform.position, movePos, Speed * Time.deltaTime);
            yield return null;
        }

        // 탱크가 목표 위치에 도달하면 저장된 위치 초기화
        targetPosition = Vector3.zero;
    }
}

 

 

 

 

 

[SerializeField] private Sprite image1;

[SerializeField] private Image image1;

두개의 차이

 

 

'산대특 > 게임 클라이언트 프로그래밍' 카테고리의 다른 글

Quaternion  (1) 2024.03.04
Dodge game  (0) 2024.03.04
코루틴 연습  (0) 2024.03.03
StarCraft - DropShip Logic  (0) 2024.02.28
Find the nearest object  (0) 2024.02.27

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BionicUnit
{
    public enum BionicUnitType
    {
        Marine,
        Medic
    }
    public BionicUnitType type;
    public string name;
    public BionicUnit(BionicUnitType type, string name)
    {
        this.type = type;
        this.name = name;
    }

}

 

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class DropShip : MonoBehaviour
{
    //마린과 메딕을 관리할 리스트
    public List<BionicUnit> units = new List<BionicUnit>();
    //최대로 태울 수 있는 인원의 수
    public const int CAPACITY = 8;
    void Start()
    {
        //생성자를 만든다
        BionicUnit medic = new BionicUnit(BionicUnit.BionicUnitType.Medic, "메딕");
        BionicUnit marine1 = new BionicUnit(BionicUnit.BionicUnitType.Marine, "마린1");
        BionicUnit marine2 = new BionicUnit(BionicUnit.BionicUnitType.Marine, "마린2");
        BionicUnit marine3 = new BionicUnit(BionicUnit.BionicUnitType.Marine, "마린3");
        BionicUnit marine4 = new BionicUnit(BionicUnit.BionicUnitType.Marine, "마린4");
        BionicUnit marine5 = new BionicUnit(BionicUnit.BionicUnitType.Marine, "마린5");
        BionicUnit marine6 = new BionicUnit(BionicUnit.BionicUnitType.Marine, "마린6");
        BionicUnit marine7 = new BionicUnit(BionicUnit.BionicUnitType.Marine, "마린7");
        BionicUnit marine8 = new BionicUnit(BionicUnit.BionicUnitType.Marine, "마린8");

        LoadUnit(medic);
        LoadUnit(marine1);
        LoadUnit(marine2);
        LoadUnit(marine3);
        LoadUnit(marine4);
        LoadUnit(marine5);
        LoadUnit(marine6);
        LoadUnit(marine7);
        LoadUnit(marine8);
        UnLoad(medic);
        UnLoadAll();
    }
    public void LoadUnit(BionicUnit unit)
    {
        if (units.Count >= CAPACITY)
        {
            Debug.Log("<color=red> 자리가 없어서 탑승에 실패 </color>");
        }
        else
        {
            units.Add(unit);
            Debug.LogFormat("{0}이 탑승했습니다. ({1}/{2})", unit.type, units.Count, CAPACITY);
            //Debug.LogFormat("{0}이 탑승했습니다. ({1}/{2})", unit.name, units.Count, CAPACITY);
        }
    }
    public void UnLoad(BionicUnit unit)
    {
        this.units.Remove(unit);
        Debug.LogFormat("{0}이 하차했습니다. ({1},{2})", unit.type, units.Count, CAPACITY);
    }
    public void UnLoadAll()
    {
        Debug.Log("모두 하차 시작");
        foreach (BionicUnit unit in units.ToList())
        //()이나 Start() 메서드에서 units 리스트를 수정하지 않도록 합니다. 리스트를 수정할 필요가 있다면 반복문 밖에서 수정
        {
            UnLoad(unit);
        }
    }
}

이런식으로 .ToList()를 쓰지 않으면 오류가 난다.

이유를 찾아보니 멤버변수에 선언한 "원본" 리스트를 변경시키기 때문에 나는 현상이라고 한다.

따라서 해결방법은 list를 새로 만들어서 다시 copy본으로 저장을 하거나

.ToList()를 사용하면된다.

 

자바스크립트에서 문자열을 자를 때 사용하는 splice와 같은 개념인가?

✔ Array.prototype.splice()

 

 

 

 

 

 

만약 unit을 하나씩이 아닌 원하는 수만큼 내리게 하고 싶다면?

int형으로 인자를 하나 더 받으면 된다.

 

'산대특 > 게임 클라이언트 프로그래밍' 카테고리의 다른 글

Quaternion  (1) 2024.03.04
Dodge game  (0) 2024.03.04
코루틴 연습  (0) 2024.03.03
StarCraft - Tank  (0) 2024.02.29
Find the nearest object  (0) 2024.02.27

 

 

표적이 되는 다른 객체들은 assign할 수 만 있도록 MonsterController 스크립트만 할당 한 후

PlayerController에서 MonsterController 인스턴스로 배열을 선언 한후 

각각의 오브젝트를 assign

 

 

https://learn.microsoft.com/ko-kr/dotnet/api/system.collections.generic.list-1?view=net-8.0

 

List<T> 클래스 (System.Collections.Generic)

인덱스로 액세스할 수 있는 강력한 형식의 개체 목록을 나타냅니다. 목록의 검색, 정렬 및 조작에 사용할 수 있는 메서드를 제공합니다.

learn.microsoft.com

 

https://docs.unity3d.com/ScriptReference/Vector3.Distance.html

 

Unity - Scripting API: Vector3.Distance

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com

 

코딩을 리뷰해보니 어려운 코드는 없었다.

가장 어려운 부분은 구조를 짜는 것이라 생각하는데

그 중에 인스턴스를 생성하거나 리스트를 생성했을때

값이 어떻게 이동되는지 이름만 옮겨지는지 이름과 값이 함께 쌍으로 넘어가는지 이 부분이 어려웠다.

Debug로 콘솔에 많이 찍어보고 값이 어떻게 출력이 되는지 확인하는데 시간을 가장 많이 썼다.


 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public MonsterController[] monsters;
    void Start()
    {
        List<MonsterController> list = new List<MonsterController>();
        for (int i = 0; i < monsters.Length; i++)
        {
            //몬스터컨트롤러의 인스턴스 생성
            MonsterController controller = monsters[i];
            //Debug.Log(controller);
            //플레이어와의 거리 구하기
            float distance = Vector3.Distance(this.transform.position, controller.transform.position);
            //Debug.LogFormat("이름 : {0}, 거리 : {1}",controller.gameObject.name, distance);
            //Debug.Log(controller.gameObject.name);

            if (distance <= 10)
            {
                list.Add(controller); //객체 형태로 담긴다 
            }
        }
        
        for(int i = 0; i < list.Count; i++)
        {
            MonsterController controller = list[i];
            float distance = Vector3.Distance(this.transform.position, controller.transform.position);
            //Debug.LogFormat("이름 : {0} , 거리 : {1}", controller.gameObject.name, distance);
        }





        //거리가 제일 가까운 객체 찾기
        float minDistance = Mathf.Infinity; // 초기값을 무한대로 지정
        MonsterController minObject = null; // 초기값을 담을 인스턴스 생성

        for(int i = 0; i < list.Count;i++)
        {
            MonsterController controller = list[i];
            float distance = Vector3.Distance(this.transform.position, controller.transform.position);
            if (distance < minDistance)
            {
                minDistance = distance;
                minObject = controller;
            }
        }
        Debug.LogFormat("거리가 가장 가까운 객체 : {0}, 거리 : {1}", minObject.name, minDistance);
    }
}​

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CSightVisualizer : MonoBehaviour
{
    public float radius = 3;
    private void OnDrawGizmos()
    {
        GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, radius);
    }
}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonsterController : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

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

'산대특 > 게임 클라이언트 프로그래밍' 카테고리의 다른 글

Quaternion  (1) 2024.03.04
Dodge game  (0) 2024.03.04
코루틴 연습  (0) 2024.03.03
StarCraft - Tank  (0) 2024.02.29
StarCraft - DropShip Logic  (0) 2024.02.28

+ Recent posts