용어

Ethernet : Ether (빛의 매질)

MAC 주소(Media Access Control Address) : 48 bit로 이루어진 숫자

 

 

네트워크 계층(Network Layer)

IPv4 (Internet Protocol Version 4) -> IPv6

IP 주소 (32bit, 8bit * 4)

ARP (Address Resolution Protocol, 주소 결정 프로토콜)

바꿔주는 프로토콜(형변환?)

- IP -> MAC 

서브넷 마스크 (Subnet Mask)

 

같은곳에서 왔는지 알수있는거 AND 비트 연산

Ex )

255.255.255.0 와 IP를 비교해서

A : 18.17.100.1 -> 18.17.100.0

B : 18.17.100.2 -> 18.17.100.0

C : 18.17.200.1 -> 18.17.200.0

앞쪽 숫자가 같으면 같은곳에 나온것으로 판단

 

게이트웨이 (Gateway)

 

전송 계측 (Transport Layer)

Port (16bit 부호없는 숫자) ex) 8000

사용자 포트 or 등록 포트, 시스템 포트 or 예약 포트, 동적포트

소켓 (Socket)

전송 제어 프로토콜 TCP - 갔는지 안갔는지 검사 해줌

사용자 데이터그램 프로토콜 UDP - 검사안함 대신 빠름

 

 

TCP Header - 정보를 전송할때 그 값에 대한 정보

 

응용 계층 (Application Layer)

DHCP(Dynamic Host Configuration Protocol)

 아이피 변경 시에도 보내줌

 동적 호스트 설정 프로토콜

DNS (Domain Name System)

 도메인 - > 아이피 주소 상호바꿔주는 역활

NAT (Network Address Translation, 네트워크 주소 변환)

 

용어정리

패킷(Packet) - 네트워크로 보낼 수 있는 최소단위

라우팅 (Routing) - 네비게이션

 

오버플로우 (Overflow) - 용량 넘음

레이턴시 (Latency) - 반응속도

타임 아웃 (Time Out)

 

직렬화 재 정렬, 역직렬화 재 정렬한걸 풀어줌

빅 엔디언(Big-Endian) 바이트를 오름차순 정렬

리틀 엔디언 바이트를(Little_Endian) 내림차순 정렬

 

Scale Out : 서버 대수 증가

Scale Up : 서버 크기 증가

 

게임서버의 역할 분산

사용자 인증만을 담당하는 '인증 서버'

사용자가 먹는 아이템이나 키운 캐릭터 정보를 저장하는 '데이터베이스 서버'

랭킹을 보여주기 위한 '통계 서버'

해킹 차단을 하기 위한 '미들웨어 서버'와 ' 방화벽 머신'

인던이나 방 만들기를 담당하는 '로비 서버'

게임을 플레이하면서 사람들과 같이하는것 'Zone 서버'

'NPC 서버' 등등

을 관리하는 ' 중앙 서버 관리자'

'로그 서버'

 

조용어

Ethernet : Ether (빛의 매질)

 

MAC 주소(Media Access Control Address) : 48 bit로 이루어진 숫자

 

 

 

 

 

네트워크 계층(Network Layer)

IPv4 (Internet Protocol Version 4) -> IPv6

 

IP 주소 (32bit, 8bit * 4)

 

ARP (Address Resolution Protocol, 주소 결정 프로토콜)

 

바꿔주는 프로토콜(형변환?)

 

- IP -> MAC 

 

서브넷 마스크 (Subnet Mask)

 

 

 

같은곳에서 왔는지 알수있는거 AND 비트 연산

 

Ex )

 

255.255.255.0 와 IP를 비교해서

 

A : 18.17.100.1 -> 18.17.100.0

 

B : 18.17.100.2 -> 18.17.100.0

 

C : 18.17.200.1 -> 18.17.200.0

 

앞쪽 숫자가 같으면 같은곳에 나온것으로 판단

 

 

 

게이트웨이 (Gateway)

 

 

 

전송 계측 (Transport Layer)

Port (16bit 부호없는 숫자) ex) 8000

 

사용자 포트 or 등록 포트, 시스템 포트 or 예약 포트, 동적포트

 

소켓 (Socket)

 

전송 제어 프로토콜 TCP - 갔는지 안갔는지 검사 해줌

 

사용자 데이터그램 프로토콜 UDP - 검사안함 대신 빠름

 

 

 

 

 

TCP Header - 정보를 전송할때 그 값에 대한 정보

 

 

 

응용 계층 (Application Layer)

DHCP(Dynamic Host Configuration Protocol)

 

 아이피 변경 시에도 보내줌

 

 동적 호스트 설정 프로토콜

 

DNS (Domain Name System)

 

 도메인 - > 아이피 주소 상호바꿔주는 역활

 

NAT (Network Address Translation, 네트워크 주소 변환)

 

 

 

용어정리

패킷(Packet) - 네트워크로 보낼 수 있는 최소단위

 

라우팅 (Routing) - 네비게이션

 

 

 

오버플로우 (Overflow) - 용량 넘음

 

레이턴시 (Latency) - 반응속도

 

타임 아웃 (Time Out)

 

 

 

직렬화 재 정렬, 역직렬화 재 정렬한걸 풀어줌

 

빅 엔디언(Big-Endian) 바이트를 오름차순 정렬

 

리틀 엔디언 바이트를(Little_Endian) 내림차순 정렬

 

 

 

Scale Out : 서버 대수 증가

 

Scale Up : 서버 크기 증가

 

 

 

게임서버의 역할 분산

 

사용자 인증만을 담당하는 '인증 서버'

 

사용자가 먹는 아이템이나 키운 캐릭터 정보를 저장하는 '데이터베이스 서버'

 

랭킹을 보여주기 위한 '통계 서버'

 

해킹 차단을 하기 위한 '미들웨어 서버'와 ' 방화벽 머신'

 

인던이나 방 만들기를 담당하는 '로비 서버'

 

게임을 플레이하면서 사람들과 같이하는것 'Zone 서버'

 

'NPC 서버' 등등

 

을 관리하는 ' 중앙 서버 관리자'

 

'로그 서버'

 

 

비동기, 동기 온라인 방식이 있고 섞어서 주로 사용

 

Network Topology

Client / Server 방식

P2P (Peer to Peer) 방식 - 유저 전체 서버

Host 기반 P2P (Super Peer) 유저 한명이 서버

 

두 방식을 섞어서도 사용

 

Clinet / Server 방식

전용 서버 (Dedicatsed Server)

 단일 서버

장점

 서버 단독 처리

 일관성 있는 결과 및 동기화

 해킹이나 핵 사용에 강함

 대규모 유저 상호작용 가능

단점

 게임서버 로직의 부담

 개발 기술 및 유지보수 비용

 모든 클라이언트가 서버를 경유해야하므로 응답성 떨어짐

 서버의 부하나 통신 지연 등으로 인해 정교한 액션 처리 어려움

 

P2P

 리슨 서버 (Listen Server)

  Host Server

  유저 한명이 서버

 P2P

  모두가 호스트

장점

 메시지를 직접 상대방에게 전달

 네트워크 지연 최소화

 클라이언트에서 로직을 처리하므로 정교하고 빠른 처리 가능

 서버의 부담이 적음

단점

 핵, 치트 등에 취약

 개별적인 로직 처리로 동기화 어려움 (충돌 처리 등)

 

네트워크 기법

 전달 미보장 데이터

 전달 보장 데이터

 최신 상태 데이터

 특급 전달 보장 데이터

 

 결정론적 락스텝 (Deterministic Lockstep)

 위치가 아닌 입력 값 넘기기

 

 데드 레커닝 (Dead Reckoning)

  네트워크가 다음 동작을 예측해서 입력해줌(인터넷이 끊겨도)

  플레이어의 다음 행동을 예측해서 적의 동작을 예측

 

네트워크 엔진 (섞어서도 사용)

로그인, 데이터베이스 - Firebase(모바일), PlayFab

엔진 - photon, ProudNet(철권, 스트리트파이터)

'수업 일기장' 카테고리의 다른 글

Unity 3D Dark Souls 따라하기  (0) 2021.03.30
Untiy.7 Move, add, sound  (0) 2021.02.26
Unity.6 uv, 텍스쳐 Wrap mode  (0) 2021.02.26
Unity.5 uv, normals, triangles  (0) 2021.02.26
Unity.4 Collider, Rigidbody  (0) 2021.02.24

Input System 새로운 조작 시스템을 받아서 사용한다.

이런식으로 설정 대략적으로 WASD 이동과 시점은 마우스 조작과 스틱 조작 두개를 넣어준거 같다.

설정 시 카메라 액션값을 아래 처럼 바꾸지 않을 시 버튼이 초기값이므로 컨트롤 타입을 벡터2 값으로 안 바꿔주면

패드 조작과 마우스 조작 빌딩이 활성화가 안된다. 마우스 조작은 노멀라이즈 벡터2 정규화를 해준다.

Ps. +를 누르면 추가된다

/* 하지만 직접 기계를 연결하여 키를 입력 받는게 있다. 자세한건 밑에 링크

Ace Combat Zero: 유니티로 구현하기 #1 : Input (velog.io)

무튼 따라하기니까 이건 배워만 두자 */

 

이제 코드로 WASD를 구현해보자.

InputHandler.cs

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


namespace SG
{
    public class InputHandler : MonoBehaviour
    {
        public float horizontal;
        public float vertical;
        public float moveAmount;
        public float mouseX;
        public float mouseY;

        PlayerCtrl inputActions;

        Vector2 movementInput;
        Vector2 cameraInput;

        // 스크립트가 활성화 될때 실행
        public void OnEnable()
        {
            // 입력값이 null인지 확인
            if (inputActions == null)
            {
                inputActions = new PlayerCtrl();
                // 인풋 매니저에 입력해논 PlayerMovement를 실행 확정 시 호출 더 빠른건 Started가 있다.
                // 설정해논 키를 입력 할때마다 현재는 WASD
                // inputActions 입력 액션, 의 값을 Read Value 읽어서 movementInput 미리 만들어논 벡터2에 넣는다. 
                // movementInput 벡터값보다 플레이어가 입력된 inputActions 값이 크면 그 값을 더해준다. 어디에 더해주냐? 그것도 문제
                inputActions.PlayerMovement.Movement.performed += inputActions => movementInput = inputActions.ReadValue<Vector2>();
                inputActions.PlayerMovement.Camera.performed += i => cameraInput = i.ReadValue<Vector2>();
            }
            // 플레이어 컨트롤 스크립트 활성화
            inputActions.Enable();
        }
        // 컴포넌트가 비활성화 될때 작동
        private void OnDisable()
        {
            //컴포넌트를 비활성화
            inputActions.Disable();
        }

        // 유추해서 보면 껏다 켰다 관리해줘야함
        public void TickInput(float delta)
        {
            // TickInput이란 메서드가 대신 받아서 줌
            MoveInput(delta);
        }
        // 숨김 위에서 대신 받아서 넘겨줌
        private void MoveInput(float delta) 
        {
            // 이동값
            horizontal = movementInput.x;
            vertical = movementInput.y;

                        //Mathf.Clamp01 0에서 1에 값을 돌려줌 ,  Math.Abs 절대값 반환
            moveAmount = Mathf.Clamp01(Mathf.Abs(horizontal) + Mathf.Abs(vertical));

            // 마우스 이동 값
            mouseX = cameraInput.x;
            mouseY = cameraInput.y;
        }
    }
}

PlayerLocomotion.cs

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

namespace SG
{
    public class PlayerLocomotion : MonoBehaviour
    {
        Transform camObj;
        InputHandler inputHandler;
        Vector3 moveDirection;

        [HideInInspector]
        public Transform myTransform;

        public new Rigidbody rigidbody;
        public GameObject normalCamera;

        [Header("스피드값")]
        [SerializeField]
        float movementSpeed = 5f;
        [SerializeField]
        float rotationSpeed = 10f;

        private void Start()
        {
            rigidbody = GetComponent<Rigidbody>();
            inputHandler = GetComponent<InputHandler>();
            // 메인 카메라 위치값
            camObj = Camera.main.transform;
            // 내 위치
            myTransform = transform;
        }

        public void Update()
        {
            // 평균 프레임 값
            float delta = Time.deltaTime;

            inputHandler.TickInput(delta);
                           // 카메라 위치 * 플레이어 입력 값
            moveDirection = camObj.forward * inputHandler.vertical;
            moveDirection += camObj.right * inputHandler.horizontal;
            // 정규화(이동속도 정규화 같은 느낌 대각선에 경우 이동속도가 빨리질 수 있으므로)
            moveDirection.Normalize();

            float speed = movementSpeed;
            // 스피드 값 계산
            moveDirection *= speed;
            // 평면에 벡터를 투영한다.        평면 위의 벡터 위치입니다(범선), 벡터에서 평면을 향한 방향입니다.
            Vector3 projectedVelocity = Vector3.ProjectOnPlane(moveDirection, normalVector);
            // 리지드 바디 속력 벡터 = 벡터
            rigidbody.velocity = projectedVelocity;
        }
        // #region 접는 기능
        #region Movement
        Vector3 normalVector;
        Vector3 targetPosition;

        // 회전 함수
        private void HandleRotation(float delta)
        {
            // 벡터값 초기화
            Vector3 targetDir = Vector3.zero;
            // inputHandler.moveAmount, 이동 값 받아옴
            float moveOverride = inputHandler.moveAmount;

            // 카메라 회전 카메라.forward * 캐릭터.vertical 타겟 디렉토리에 넣어둠
            targetDir = camObj.forward * inputHandler.vertical;
            // left로 갈 시 음수 값이라 뒤집힘
            targetDir += camObj.right * inputHandler.horizontal;
            targetDir.Normalize();
            // 목표 방향이 같은 경우 움직임을 원치 않기 때문에
            targetDir.y = 0;
            
            // 앞 보게
            if (targetDir == Vector3.zero)
                targetDir = myTransform.forward;

            // 회전 속도
            float rs = rotationSpeed;

            // 타겟에 쿼터니언 값 반환
            Quaternion tr = Quaternion.LookRotation(targetDir);
            //회전 시켜줄 값 반환                 회전할 캐릭터 디폴트 값, 타켓 쿼터니언값, 스피트*델타
            Quaternion targetRotation = Quaternion.Slerp(myTransform.rotation, tr, rs * delta);
            // 회전을 값에 적용
            myTransform.rotation = targetRotation;
        }
        #endregion
    }
}

 

 

 

'수업 일기장' 카테고리의 다른 글

네트워크 수업 (1)  (0) 2021.04.20
Untiy.7 Move, add, sound  (0) 2021.02.26
Unity.6 uv, 텍스쳐 Wrap mode  (0) 2021.02.26
Unity.5 uv, normals, triangles  (0) 2021.02.26
Unity.4 Collider, Rigidbody  (0) 2021.02.24

Move 새로운 움직임 방식

회전까지 

float xAxis = Input.GetAxis("Horizontal");
float yAxis = Input.GetAxis("Vertical");
MoveToDir(new Vector3(xAxis,0, yAxis));

Horizontal, Vertical 유니티에서 제공해주는 방식이다, 움직임 외에 여러가지가 있다.

원래 W,D를 받는 방식과 다르다

 

회전 코드

 if(Input.GetKey(KeyCode.Q))
        {
            transform.Rotate(Vector3.up, -rotSpeed * Time.deltaTime); 
        }
 
 
 
 if (Input.GetKey(KeyCode.E))
        {
            transform.Rotate(Vector3.up, rotSpeed * Time.deltaTime); 
        }

Q를 받으면 왼쪽으로 E를 받으면 오른쪽으로 회전하는 형식이다. 

벡터값이므로 x,y 반대 방향 음수양수를 구분해서 속도값을 줘야한다. 잘못 줄 시 반대 방향으로 돌아감.

 

 

tip. 축을 기준으로 회전이나, 스케일을 키우는게 달라짐 이걸 생각하고 곱하고 더하는걸 생각해야함
            transform.Translate(벡터,속도,델타타임) 이동
            transform.RotateAround 기점을 두고 주위를 회전
            1 / 60 deltaTime , 1 / 50 fixedDeltaTime(고정)

        if (Input.GetKey(KeyCode.W))
            MoveToDir(transform.forward);
        if (Input.GetKey(KeyCode.S))
            MoveToDir(transform.forward * -1f);
        if (Input.GetKey(KeyCode.A))
            MoveToDir(transform.right * -1f);
        if (Input.GetKey(KeyCode.D))
           MoveToDir(transform.right);

Vector는 월드 기준 좌표 그러므로 벡터로 캐릭터를 움직이면 캐릭터가 회전을 해도 방향은 바끼지 않는다
transform으로 바꿔주면 자기기준으로됨 대신 음수로 움직이는게 없음 back , left 그러므로 반대 방향에 -1f를 곱해준다

 

이제 sound 아이템 먹을때 사운드를 만들껀데

배경 음악은 일단 Audio Source라는 컴퍼넌트를 사용하면 된다.

 

먹을 때 사운드를 낼 때를 구현하면 코드는 이렇다.

public void DeadProcess()
    {
        AudioClip[] clips = Resources.LoadAll<AudioClip>("CasualGameSounds");
        //AudioClip clip = Resources.Load<AudioClip>("파일명\\파일명.확장자"); 
        하나만 불러올때 이런 코드를 사용 , 오디오는 항상 Resources 파일이 있어야함

        //audio.clip = clips[0];
        //audio.Play();
        //audio.volume = 0.5f; 볼륨 조절 가능

        audio.PlayOneShot(clips[Random.Range(0, clips.Length)]); //한번 실행해주는 코드 PlayOneShot

        Invoke("SelfDestroy", 0.5f);
    }
    
        private void SelfDestroy()
    {
        Destroy(gameObject); //자신을 파괴
    }

파일 여러개를 불러올때는 배열로 생성

 

 

'수업 일기장' 카테고리의 다른 글

네트워크 수업 (1)  (0) 2021.04.20
Unity 3D Dark Souls 따라하기  (0) 2021.03.30
Unity.6 uv, 텍스쳐 Wrap mode  (0) 2021.02.26
Unity.5 uv, normals, triangles  (0) 2021.02.26
Unity.4 Collider, Rigidbody  (0) 2021.02.24

uv는 앞에서 설명했듯이 이미지 비율을 찍어주는것이다 밑에 코드를 보면

   MeshFilter mf = GetComponent<MeshFilter>();
   Mesh mesh = mf.mesh;
   
   mesh.uv = new Vector2[]
        {
            new Vector2(0f, 0.5f) , new Vector2(0.5f, 0.5f),
            new Vector2(0f,1f), new Vector2(0.5f,1f)
        }; 

일단 왼쪽 이미지는 원본이며 오른쪽 이미지가 코드를 작성 후 나온 이미지이며 왼쪽위가 짤린채로 나옵니다.

음수가 없는걸 생각해보면 uv는 사각형 모양으로 자르는 형태로 이미지를 불러옵니다. 순서대로 자른다고 생각합니다.

그러니 맨처음 시작은 왼쪽 위부터 시작인거죠

   mesh.uv = new Vector2[]
        {
            new Vector2(0f, 0.5f) , new Vector2(0.5f, 0.5f),
            new Vector2(0f,2f), new Vector2(0.5f,2f)
        }; 

다음 코드입니다. 위에 사진을 보면 짤린건 맞는데 아래가 더 늘어났습니다. 1f 부분을 2f로 바꿔줬습니다.

세로가 두배로 늘어나 짤린 부분을 이미지에서 설정한 값으로 다시 채워준겁니다.

uv는 이해했다고 생각합니다.

이제 채우는 방식입니다. 이 설정은 텍스쳐 파일에 있습니다.

 

 

 

 

 

 

 

 

 

Wrap Mode 이 부분입니다.

Repeat

Clamp

Mirror

등이 있습니다.

 

Clamp / Repeat / Mirror 순입니다.

'수업 일기장' 카테고리의 다른 글

Unity 3D Dark Souls 따라하기  (0) 2021.03.30
Untiy.7 Move, add, sound  (0) 2021.02.26
Unity.5 uv, normals, triangles  (0) 2021.02.26
Unity.4 Collider, Rigidbody  (0) 2021.02.24
Unity.3 기초 및 Prefabs  (0) 2021.02.24

이제부턴 수업 역순으로 올라가는 식으로 적겠습니다.

 

매쉬를 코드로 생성해볼껍니다.

vertices -> uv -> normals -> triangles 순으로 만들어야합니다.

일단 빈 게임 오브젝트를 생성합니다.

 그 후 스크립트 생성하고 매쉬를 생성할 게임 오브젝트를 동적할당해줍니다.

        GameObject go = new GameObject();
        go.name = "Handmade GameObject";
        go.tag = "Player";
        
        MeshFilter mf = go.AddComponent<MeshFilter>();
        Mesh mesh = new Mesh();
        mesh.name = "HandmadeMesh";

매쉬필터 컴포지션을 가져오고 매쉬를 동적할당합니다.

 

 

버텍스(vertices) 정점이라는 뜻으로 점을 찍습니다.

중심점을 잡고 시작합니다. 게임오브젝트란걸 생성해놨으므로 그게 중심이 됩니다.

-0.5,0.5,0 --- 0.5,0.5,0

      |                |

-0.5,-0.5,0----0.5,-0.5,0

x, y, z 값까지 씁니다.

 

매쉬를 생성할 시 버텍스 부분 코드

 mesh.vertices = new Vector3[]
        {
            new Vector3(-0.5f, 0.5f,0f), new Vector3(0.5f,0.5f, 0f),
            new Vector3(-0.5f, -0.5f, 0f) ,new Vector3(0.5f, -0.5f, 0f)
        };

 

uv는 좌표의 이름이며 엔진마다 시작위치는 다르지만 일단 유니티 상에선 0 ~ 1로 비율을 구할때 사용하며 유니티에 경우 좌표는 x,y로 왼쪽 아래 부터 시작합니다.

사각형을 그려보면 

0 , 1 --- 1 , 1

  |           |

0 , 0 ----1 , 0

(시작) 이런식으로 그려집니다.

메쉬를 생성할 시 코드

   mesh.uv = new Vector2[]
        {
            new Vector2(0f, 1f), new Vector2(1f,1f),
            new Vector2(0f, 0f), new Vector2(1f,0f)
        };

다음으로 normals(법선)이란 뜻을 찾아보니 버텍스에 수직을 향하는 방향

말그대로 빛을 받고 반사하는 방향을 가르키는거라고 합니다.

현재 평면 판넬을 만들어 Z축의 반대로 그림을 보여줄꺼니 코드는 이렇습니다.

  mesh.normals = new Vector3[]
        {
            new Vector3(0f,0f,-1f), new Vector3(0f,0f,-1f),
            new Vector3(0f,0f,-1f), new Vector3(0f,0f, -1f)
        };

Z축을 다 -1f 을 해줬습니다. 빛을 받는게 아님 반사하는 방향임을 기억해야합니다.

마지막으로 triangles 먼저 코드를 보겠습니다.

mesh.triangles = new int[]
        {
            0,1,2,   //  0 ----1
                     // |      |
                     // 2 ---- 3
            1,3,2
        };

인트 배열로 만들어서 옆에 사각형을 만들어 좀 더 이해를 도왔습니다.

따라가다 보면 CW(시계방향)으로 삼각형을 그립니다.

삼각형을 그려서 둘을 합쳐 사각형을 만들어야함으로 그렇게 하였습니다.

시계방향으로만 돌면 상관없습니다.

그 후 렌더러를 하는 형식입니다.

mf.mesh = mesh;

        MeshRenderer mr = go.AddComponent<MeshRenderer>();
        Material mat = new Material(Shader.Find("Standard"));
        mat.name = "M_Handmade";
        mat.mainTexture = Resources.Load<Texture2D>("Textures\\Character");

        mr.material = mat;
    }

렌더러 컴포지션을 불러오고 머테리얼을 만들어줍니다. 하지만 머테리얼은 기본적으로 매개변수가 필요합니다.

쉐이더를 만들어논게 없으므로 기본 쉐이더인 Standard를 입혀줍니다.

그리고 마지막으로 텍스쳐를 불러와 입혀줍니다. Resources 파일을 만들어줍니다. 파일명은 바껴선안됩니다.

모든 그림은 Texture2D을 필요로 합니다. 컴포지션을 불러오고 파일경로\\파일명" 해줍니다. .png .jpg는 빼줍니다.

그리고 마지막으로 mr MeshRenderer에 머테리얼에 입혀줍니다.

'수업 일기장' 카테고리의 다른 글

Untiy.7 Move, add, sound  (0) 2021.02.26
Unity.6 uv, 텍스쳐 Wrap mode  (0) 2021.02.26
Unity.4 Collider, Rigidbody  (0) 2021.02.24
Unity.3 기초 및 Prefabs  (0) 2021.02.24
Unity.2 UI/UX 및 버튼 이동  (0) 2021.02.24

Collider

충돌박스,히트박스 같은것 같다. Trigger는 한번 충돌판정 Collision는 여러번 충돌판정

 

Rigidbody

충돌판정을 처리해야하는 오브젝트는 Rigidbody가 있어야함 물리가 없으면 충돌판정 자체가 안되므로,

판정이 필요한 곳만 필요하다.

    private void OnCollisionEnter(Collision collision) //엑시트,스테이
                                                       //충돌판정을 처리해야하는 오브젝트는 Rigidbody가 있어야함
    {
        if (collision.gameObject.CompareTag("Player"))
                              //.tag == "Player" 같은거
        {
            Debug.Log(collision.gameObject.name);
		}
    }

아이템을 뿌려줌

public class ItemManager : MonoBehaviour
{
    [SerializeField] private GameObject itemPrefab = null;

    private void Start()
    {
        for (int i = 0; i < 100; i++)
        {
            Instantiate(itemPrefab, new Vector3(Random.Range(-30f, 30f), 2f, Random.Range(-30f, 30f)), Quaternion.identity);
        }
    }
}

 

오브젝트가 닿은 상대가 playerTag면 없애는 함수 몬스터에게 준 상태

Destroy(매개변수.gameObject)

private void OnTriggerEnter(Collider other)
    {
        if(other.gameObject.CompareTag("Player"))
        {
            Debug.LogWarning(other.gameObject.name); // 디버깅 창에 출력
            
            Destroy(other.gameObject); //지정해서 없애는 함수
        }
    }

 

내나 위와 같은 방식으로 플레이어가 아이템 태그에 닿으면 아이템태그를 가진 오브젝트가 사라지는 형태

 private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Item"))
        {
            Destroy(other.gameObject);
            ++itemCnt;  // 카운터
            Debug.Log("Item Count :" + itemCnt); // 카운터 숫자를 띄워줌
        }
    }
}

 

 

Collision은 매개변수로 Collision을 받고

Trigger는 매개변수로 Collider를 받는다.

moveToDir.enabled = false;    스크립트 Off
gameObject.SetActive(false);  게임오브젝트 Off

 

 

'수업 일기장' 카테고리의 다른 글

Unity.6 uv, 텍스쳐 Wrap mode  (0) 2021.02.26
Unity.5 uv, normals, triangles  (0) 2021.02.26
Unity.3 기초 및 Prefabs  (0) 2021.02.24
Unity.2 UI/UX 및 버튼 이동  (0) 2021.02.24
Unity.1 이동 및 추격  (0) 2021.02.19

 

Prefabs - 복제하는 대신 메모리를 한 오브젝트의 메모리만 사용합니다. 수정 후 Overrides 할 경우 한번에 편집이 가능합니다. 프리팹을 열어서 편집 시 자동으로 저장됩니다.

기본 GameObject형이며 모든 오브젝트를 만들고 다 Prefabs화를 시켜주는게 좋습니다.

Random.Range ( 범위 , 범위 ) - 랜덤 값을 구하는것이며 float 형과 int 형 사용 가능하며 int형은 최대값을 포함하지 않으며 float은 포함한다. 최소값은 다 포함합니다.

디폴트 매개변수 (Default Parameters) 앞에서부터는 못 넣습니다.

매개변수 = "기본값" 형식 

예제)

public void SpawnEnemy(Vector3 _pos, string _name = "Enemy") 

Instantiate 게임 실행중 오브젝트를 생성할 수 있다. 식은 아래와 같다.

1.

[SerializeField] private GameObject enemyPrefab = null; //프리펩 불러오기
						// 프리펩 ,  벡터값 매개변수, Quaternion.idantity)
 GameObject enemyGo = Instantiate(enemyPrefab, _pos, Quaternion.identity);

 

회전값을 구할때 Euler, Quaternion이 있다. 서로 장단점이 있습니다.

Euler는 짐벌락으로 인해 사용 안하지만 좌표값이므로 구하기는 쉽습니다. XYZ

Quaternion는 구하기는 힘들며 XYZ를 한번에 돌려줘 짐벌락이 발생하지 않는다. 구체적으론 XYZ 토대로 한번에 돌릴 수 있는 좌표값을 구해서 돌리는 겁니다.

1번 코드에선 굳이 회전을 줘야하는 상황이 아니므로 기본값인 identity를 넣었습니다.

2.

transform.retation = new Vector3(0,0,0);

transform.rotation = Quaternion.Euler(10,20,30);

2번 코드는 두개의 장점을 이용한 Quaternion.Euler(x,y,z) 값으로 사용 가능하게 해줍니다.

 

xyz 음수 양수 구별이 가능하도록 외우는게 좋습니다.

좌표를 설정할때 여러 용어들이 있습니다.

pitch - X축 자기 기준 회전, yaw - Y축 자기 기준 회전, roll - Z축 자기 기준 회전

'수업 일기장' 카테고리의 다른 글

Unity.5 uv, normals, triangles  (0) 2021.02.26
Unity.4 Collider, Rigidbody  (0) 2021.02.24
Unity.2 UI/UX 및 버튼 이동  (0) 2021.02.24
Unity.1 이동 및 추격  (0) 2021.02.19
수업 일기장 #C++(2)  (0) 2021.01.25

Scene 이동

public class NextScene : MonoBehaviour
{
    public string sceneName; // 씬 이름을 받을 String 칸
    
    public void GotoScene()
    {
        SceneManager.LoadScene(sceneName); //이름을 받고 LoadScene을 한다.
    }

}

 

오브젝트 삭제

public class ObjectVisible : MonoBehaviour
{
    public void SetVisible(bool flg)
    {
        gameObject.SetActive(flg); 
    }
}

X 버튼을 누를 시 창을 닫는 형식으로 되어있다. 팝업창에 사용

 

 

Unity 이미지를 불러오는 방법

이미지를 구하고 그 이미지를 Assets 파일 Textures 파일에 넣고 Sprite로 변경해고 Apply 해준다.

(없으면 생성 정리과정이다)

Hierarchy 창에서 오른쪽 UI / image / Source Image 에 Sprite 변경한 이미지를 넣어준다.

 

 

UI / Text 에 대한 설명은 밑에 나와있다.

말고도 여러가지 찾아볼수있다.

텍스트 - Unity 매뉴얼 (unity3d.com)

 

텍스트 - Unity 매뉴얼

텍스트(Text) 컨트롤은 사용자에게 상호작용이 되지 않는 텍스트를 표시합니다. 이를 통해 다른 GUI 컨트롤에 캡션 또는 라벨을 제공하거나, 지침 또는 다른 텍스트를 표시할 수 있습니다.

docs.unity3d.com

 

벡터를 바로 받는게 아닌 버튼 클릭 시 이동하는 방법

public class ObjectMove : MonoBehaviour
{
    public void MoveToDir1(int _dir)
    {
        switch(_dir) // int 입력값을 받고
        {
            case 1: // 1번을 입력받으면 왼쪽으로 이동
                transform.Translate(new Vector3(-1f, 0f, 0f));
                break;
            case 2: // 2번을 입력받으면 오른쪽으로 이동
                transform.Translate(new Vector3(1f, 0f, 0f));
                break;
        }
    }

}

 

위 스크립트를 생성

이동 시킬 오브젝트에 넣는다.

만들어논 버튼 UI로 돌아와 On Click 이벤트에 오브젝트를 끌어넣어준다.

오브젝트에 넣어논 스크립트를 찾아서 인트값을 넣어주면 된다. 그럼 Switch 조건에 따른 이동이 된다.

P.s - On Click 이벤트에 경우 자주 사용함

 

 

토글(체크박스)

On/Off 로 사용하며 체크가 될때 이미지를 덮어서 뒤 이미지가 안보이도록 하는 형식으로 사용한다.

 

On Value Changed (Boolean)

public void ViewFlg(bool flg)
{
	Debug.Log(flg);
}

Inspector에서 체크박스에서 값을 얻는 형태 (위 코드는 게임상 화면에서 체크박스의 false , trur 값이 Log에 찍힌다.)

또한 ViewFlg란 기본 함수도 존재한다. 같은 기능을한다.

'수업 일기장' 카테고리의 다른 글

Unity.4 Collider, Rigidbody  (0) 2021.02.24
Unity.3 기초 및 Prefabs  (0) 2021.02.24
Unity.1 이동 및 추격  (0) 2021.02.19
수업 일기장 #C++(2)  (0) 2021.01.25
수업 일기장 #클래스(Class)  (0) 2021.01.25

유니티 화면 실행 화면

 

 

유니티 기본 설명 및 이동 코드

Materials를 만들때는 Mat를 앞에 붙여씀

 

player.cs

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


public class Player : MonoBehaviour
{
    [Range(0.0f, 100f)] // 스크롤 바
    [SerializeField] // 프라이빗으로 지정하고 유니티에 띄울 수 있도록 해줌
    private float speed = 0f;  //접근 지정자를 생략 시 기본 private
             //유니티에선 변수를 퍼블릭으로 할 시 유니티 상에 수정 가능하게 표기됨
             // 코드상에서 변수명을 바꿀 시 유니티에서 입력한 값이 초기화됨
             // c#은 m_ 전역벽수가 없으므로 멤버변수 구분이 필요 없음


    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
            MoveToDir(Vector3.forward);
       
        if (Input.GetKey(KeyCode.S))
            MoveToDir(Vector3.back);
        if (Input.GetKey(KeyCode.A))
            MoveToDir(Vector3.left);
        if (Input.GetKey(KeyCode.D))
            MoveToDir(Vector3.right);
    }


    public void MoveToDir(Vector3 _dir)
    {
        //Transform이란 유니티가 만들어논 클래스를 가져와서 사용
        //Vector3 pos = this.GetComponent<Transform>().position; // 밑에 껄 풀어 씀
        Vector3 newPos = this.transform.position;              
        newPos = newPos + (_dir * speed * Time.deltaTime); //업뎃에서 가저올 필요 없이 Time에서 가져옴
        transform.position = newPos;

        // int val = new int(); // 동적 할당 c++과는 () 차이
        // Garbage Collector로 인해 C#은 따로 동적할당 해체가 필요없음.
        // 대신 포퍼먼스가 떨어지며 정리 타이밍의 컨트롤이 불가함
        // 메모리가 부족할때 작동하며 
        // 레벨이라는 개념이 있고 그건 돌때마다 살아있으면 레벨업해서 메모리 해제 우선순위에서 제외함
        // 우선순위가 잘못 매겨져 메모리가 너무 부족하면 대규모 공사함
    }
}

 

 

[Range(0.0f, 100f)]

위 코드 중 일부 인스펙터 속성 유니티 상 UI를 띄우는 방법

유니티 인스펙터 속성(Unity Inspect.. : 네이버블로그 (naver.com)

 

추격 컴퍼넌트를 작성 

MoveToDir.cs

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

public class MoveToDir : MonoBehaviour
{
    private Vector3 dir = Vector3.zero;
    public float speed{ get; set; } // 자신에게 넘길때

    //Getter / Setter C++ , C#
    //Property C#
    public Vector3 Dir
    {
        get { return dir; }
        set { dir = value; }
    } 
    // 받아서 다른 곳에 넘길때


    private void Update()
    {
        MoveToDirection();
    }
    private void MoveToDirection()
    {
        Vector3 newPos = transform.position;
        newPos += dir * speed * Time.deltaTime;
        transform.position = newPos;
    }
}

C#에선 get; set;을 위와 같이 두 부류로 사용

 

 

추격 컴퍼넌트를 사용한 코드

Enemy.cs

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


public class Enemy : MonoBehaviour
{
    [SerializeField] private GameObject targetGo = null; //게임 오브젝트 받음
    [SerializeField] private Transform targetTr = null; //트랜스 폼을 바로 받음
    [SerializeField] private float speed = 7f;
    //private readonly float speed = 7f; 상수 const 도 가능

    private MoveToDir moveToDir = null;

    private void Awake() // Startup 과정에서 Start보다 빨리 호출되는 객체
    {
        moveToDir = GetComponent<MoveToDir>();
        moveToDir.speed = speed;
    }


    private void Update()
    {
        if (targetTr == null) return;

        //Transform tr = targetGo.GetComponent<Transform>();
                      //타켓 포지션(플레이어) - 몬스터(this)
        Vector3 dir = targetTr.position - transform.position;
        dir.Normalize(); //벡터 정규화
        //MoveToDir(dir); 
        moveToDir.Dir = dir;
     
    }

    //private void MoveToDir(Vector3 _dir)
    //{
    //    Vector3 newPos = transform.position;
    //    newPos += _dir * speed * Time.deltaTime;
    //    transform.position = newPos;
    //}
}

 

유니티 라이프 사이클(Unity Lifecycle) 호출 되는 순서이며

유니티는 한개를 컴파일하는 형식이 아닌 다 호출해놓고 실행 시킴, 객체지향

 

'수업 일기장' 카테고리의 다른 글

Unity.3 기초 및 Prefabs  (0) 2021.02.24
Unity.2 UI/UX 및 버튼 이동  (0) 2021.02.24
수업 일기장 #C++(2)  (0) 2021.01.25
수업 일기장 #클래스(Class)  (0) 2021.01.25
수업 일기장 #참조(Reference)  (0) 2021.01.25

main.cpp

#include <iostream>
#include "CScreen.h"
#include "CPoint.h"


void Swap(int* const _lhs, int* const _rhs);
void Swap(int& _lhs, int& _rhs);
void Swap(float* const _lhsf, float* const _rhsf);

// 디폴트 매개변수(Default Parameter, Default Argument)
int Sum(int _lhs, int _rhs = 8) { 
//기본값을 줌 (인자를 안 줄 시 기본값 5를 입력 기본값은 오른쪽부터 
//입력되어있어야 왼쪽도 입력 가능)
//오른쪽에 넣어줘도 왼쪽값 입력안해도 기본값이 들어감
	return _lhs + _rhs;
}

int Sum(int _lhs) {
	return _lhs + 5;
}

int main() {
	// 자료형(Data Type)
	// Boolean(True, False)를 저장
	bool b = true;
	// false : 0
	// true : 1
	// C에선 #define으로 정의해서 사용

	std::cout << "bool Size: " << sizeof(bool) << " Byte" << std::endl; //1바이트
	b = !b; // 값을 넣어도 0 아님 다 1(true)
			// 대입할때 복합연산자와 혼동하는것 조심
	std::cout << "b: " << b << std::endl;

	//while (true) {}

	//////////////////////////////////
	std::cout <<  std::endl;


	// 함수명은 같아도 뒤에 들어오는 자료형에 따라서 호출되는 함수가 정해지는것
	// 매개변수 자료형으로만 함수 호출을 함(반환형 불가)
	// 매개변수 인수가 들어가는 값이 달라도 결과적으로 똑같은 수의 매개변수를 사용할 시 오류가 남
	// 함수 오버로딩(Function Overloading)
	int lhs = 10, rhs = 20;
	Swap(lhs, rhs);
	std::cout << "Swap(lhs: " << lhs << ",rhs: " << rhs << ")" << std::endl;


	/////////////////////////
	std::cout << std::endl;

	std::cout << lhs << " + " << rhs << " = " << Sum(lhs,rhs) << std::endl;

	///////////////////////////////////////
	std::cout << std::endl;

	CScreen screen;
	CPoint point(1,2);
	point.SetX(4);
	point.SetY(2);
	point.Print();
	//////////////////////////////
	std::cout << std::endl;

	// 포인터
	CPoint* pPt;
	pPt = &point;
	pPt->SetY(10);
	pPt->Print();

	// 참조(Reference) - 포인터와 다르게 이름을 하나 더 만드는 형식, 그래서 바이트도 같다고 나온다. 
						// 주소값 또한 포인터와 다르게 원래 값과 동일하다.
	// 새로 만드는게 아니라서 생성과 동시에 초기화를 해줘야함
	CPoint& rPt = point;
	//rPt = point; <- 안됨
	rPt.SetX(20);
	rPt.Print();

	std::cout << "CPoint& Size: " << sizeof(rPt) << "Byte" << std::endl;
	printf("point Address: %p\n", &point);
	printf("rPt Address: %p\n", &rPt);
	printf("pPt Address: %p\n", &pPt);
	
	point.Print();

	///////////////////////////
	std::cout << std::endl;

	//깊은 복사(Deep-Copy), 얕은 복사(Shallow-Copy)
	//CPoint pt2nd(point);
	//CPoint pt2nd = point;
	CPoint pt2nd;
	pt2nd = point;
	//pt2nd.operator=(point); 풀어서
	pt2nd.Print();

	pt2nd + point;
	pt2nd.Print();

	return 0;
}

void Swap(int* const _lhs, int* const _rhs) {
	std::cout << "Swap with int Call" << std::endl;
	//NULL -> nullptr C++ 넘어오면서 사용(안정성)
	if (_lhs == nullptr || _rhs == nullptr) return;

	int tmp = *_lhs;
	*_lhs = *_rhs;
	*_rhs = tmp;
}
void Swap(int& _lhs, int& _rhs) {
	std::cout << "Swap with int Reference Call" << std::endl;
	int tmp = _lhs;
	_lhs = _rhs;
	_rhs = tmp;
}

void Swap(float* const _lhsf, float* const _rhsf) {
	std::cout << "Swap with float Call" << std::endl;
	if (_lhsf == nullptr || _rhsf == nullptr) return;
	float tmp = *_lhsf;
	*_lhsf = *_rhsf;
	* _rhsf = tmp;
}

 

CPoint.cpp

#include <iostream>
#include "CScreen.h"
#include "CPoint.h"


void Swap(int* const _lhs, int* const _rhs);
void Swap(int& _lhs, int& _rhs);
void Swap(float* const _lhsf, float* const _rhsf);

// 디폴트 매개변수(Default Parameter, Default Argument)
int Sum(int _lhs, int _rhs = 8) { //기본값을 줌 (인자를 안 줄 시 기본값 5를 입력 기본값은 오른쪽부터 입력되어있어야 왼쪽도 입력 가능) 
								  // 오른쪽에 넣어줘도 왼쪽값 입력안해도 기본값이 들어감
	return _lhs + _rhs;
}

int Sum(int _lhs) {
	return _lhs + 5;
}

int main() {
	// 자료형(Data Type)
	// Boolean(True, False)를 저장
	bool b = true;
	// false : 0
	// true : 1
	// C에선 #define으로 정의해서 사용

	std::cout << "bool Size: " << sizeof(bool) << " Byte" << std::endl; //1바이트
	b = !b; // 값을 넣어도 0 아님 다 1(true)
			// 대입할때 복합연산자와 혼동하는것 조심
	std::cout << "b: " << b << std::endl;

	//while (true) {}

	//////////////////////////////////
	std::cout <<  std::endl;


	// 함수명은 같아도 뒤에 들어오는 자료형에 따라서 호출되는 함수가 정해지는것
	// 매개변수 자료형으로만 함수 호출을 함(반환형 불가)
	// 매개변수 인수가 들어가는 값이 달라도 결과적으로 똑같은 수의 매개변수를 사용할 시 오류가 남
	// 함수 오버로딩(Function Overloading)
	int lhs = 10, rhs = 20;
	Swap(lhs, rhs);
	std::cout << "Swap(lhs: " << lhs << ",rhs: " << rhs << ")" << std::endl;


	/////////////////////////
	std::cout << std::endl;

	std::cout << lhs << " + " << rhs << " = " << Sum(lhs,rhs) << std::endl;

	///////////////////////////////////////
	std::cout << std::endl;

	CScreen screen;
	CPoint point(1,2);
	point.SetX(4);
	point.SetY(2);
	point.Print();
	//////////////////////////////
	std::cout << std::endl;

	// 포인터
	CPoint* pPt;
	pPt = &point;
	pPt->SetY(10);
	pPt->Print();

	// 참조(Reference) - 포인터와 다르게 이름을 하나 더 만드는 형식, 그래서 바이트도 같다고 나온다. 
						// 주소값 또한 포인터와 다르게 원래 값과 동일하다.
	// 새로 만드는게 아니라서 생성과 동시에 초기화를 해줘야함
	CPoint& rPt = point;
	//rPt = point; <- 안됨
	rPt.SetX(20);
	rPt.Print();

	std::cout << "CPoint& Size: " << sizeof(rPt) << "Byte" << std::endl;
	printf("point Address: %p\n", &point);
	printf("rPt Address: %p\n", &rPt);
	printf("pPt Address: %p\n", &pPt);
	
	point.Print();

	///////////////////////////
	std::cout << std::endl;

	//깊은 복사(Deep-Copy), 얕은 복사(Shallow-Copy)
	//CPoint pt2nd(point);
	//CPoint pt2nd = point;
	CPoint pt2nd;
	pt2nd = point;
	//pt2nd.operator=(point); 풀어서
	pt2nd.Print();

	pt2nd + point;
	pt2nd.Print();

	return 0;
}

void Swap(int* const _lhs, int* const _rhs) {
	std::cout << "Swap with int Call" << std::endl;
	//NULL -> nullptr C++ 넘어오면서 사용(안정성)
	if (_lhs == nullptr || _rhs == nullptr) return;

	int tmp = *_lhs;
	*_lhs = *_rhs;
	*_rhs = tmp;
}
void Swap(int& _lhs, int& _rhs) {
	std::cout << "Swap with int Reference Call" << std::endl;
	int tmp = _lhs;
	_lhs = _rhs;
	_rhs = tmp;
}

void Swap(float* const _lhsf, float* const _rhsf) {
	std::cout << "Swap with float Call" << std::endl;
	if (_lhsf == nullptr || _rhsf == nullptr) return;
	float tmp = *_lhsf;
	*_lhsf = *_rhsf;
	* _rhsf = tmp;
}

CPoint.h

// 중복 컴파일
//#ifndef _CPOINT_H_
//#define _CPOINT_H_
// 뒤에 정의가 안되어있으면 참 if'n'def , 건너뜀 #endif로 같이 사용해야함
// c에서 사용가능 c++에서도 선호
#pragma once
// 프라그마중에서 once라는 기능을 사용
// 중복 컴파일 방지 위와 아래 둘다 사용함

#include <iostream>

class CPoint {
private:
	int m_iX = 0, m_iY = 0;

public:
	CPoint();
	// 오버로딩 생성자(Overloading Constructor)
	CPoint(int _x, int _y);
	//복사 생성자(Copy Constructor)
	CPoint(const CPoint& _pt);
	~CPoint();
	
	// Getter / Setter
	// Property
	// Inline Function
	void SetX(int _x) { m_iX = _x; }
	int GetX(){ return m_iX; }
	inline void SetY(int _y) { m_iY = _y; };
	inline int GetY() { return m_iY; };//inline 검사하는거로 남용 금지 , 사용 시 정의 내용을 .h 파일에 작성해놔야함
	//스크린 좌표는 정수, 3D는 실수

	void Print();
public:
	// 연산자 오버로딩(Operator Overloading)
	// 복사 대입 연산자
	CPoint operator=(const CPoint& _pt);
	CPoint operator+(const CPoint& _pt);
};

//#endif

 

CScreen.cpp

#include "CScreen.h"

CScreen::CScreen() {
	std::cout << "CScreen Constructor Call" << std::endl;
}
	CScreen::~CScreen() {
		std::cout << "CScreen Constructor Call" << std::endl;
}

CScreen.h

#include <iostream>
#include "CPoint.h"


class CScreen {
private:
	CPoint pt;

public:
	CScreen();
	~CScreen();
};

'수업 일기장' 카테고리의 다른 글

Unity.2 UI/UX 및 버튼 이동  (0) 2021.02.24
Unity.1 이동 및 추격  (0) 2021.02.19
수업 일기장 #클래스(Class)  (0) 2021.01.25
수업 일기장 #참조(Reference)  (0) 2021.01.25
수업 일기장 #멤버 함수  (0) 2021.01.25

+ Recent posts