유니티는 레거시 애니메이션과 메카님 애니메이션이라는 두가지 유형의 애니메이션을 지원한다.

  • 레거시 애니메이션 : 하위 호환성을 고려한 애니메이션, 소스코드로 컨트롤 함. 가볍지만 새로 만든다면 메카님을 추천
  • 메카님 애니메이션 : 모션 캡쳐 애니메이션, 애니메이션을 재사용하는 Retargeting 가능. 

주인공 캐릭터는 애니메이션 타입으로 구현하고 적 캐릭터는 메카님 애니메이션을 적용해보자 

Resorces/Anmations 폴더에서 PlayerAnimation 패키지를 임포트한다.

임포트후 생성된 폴더는 07.Animations폴더로 옮긴다.

프로젝트뷰 Model/Player폴더내의 Player모델을 선택 인스펙터뷰의 위쪽  Rig탭을 선택하고 Animation Type을 Leagacy로 설정한다.

프로퍼티:기능:

Animation Type 애니메이션 타입을 지정합니다.
  None 애니메이션이 없습니다.
  Legacy 레거시 애니메이션 시스템을 사용합니다. Unity 3.x 및 이전 버전과 동일하게 애니메이션을 임포트하고 사용합니다.
  Generic 릭이 비휴머노이드(네 발 달린 생물 또는 애니메이션화할 엔티티)인 경우 제니릭 애니메이션 시스템을 사용합니다. Unity가 루트 노드를 선택하지만, 루트 노드(Root node) 로 사용할 다른 뼈대를 대신 식별할 수 있습니다.
  Humanoid 릭이 휴머노이드(두 다리와 두 팔과 머리가 있음)인 경우 휴머노이드 애니메이션 시스템을 사용합니다. 일반적으로 Unity가 골격을 감지하고 아바타에 올바르게 매핑합니다. 경우에 따라 아바타 정의(Avatar Definition) 변경사항을 설정하고 매핑을 수동으로 설정(Configure) 해야 할 수 있습니다.

하이라키뷰에서 Player의 Inspector를 보면 Animation컴포넌트가 추가되어 있다 이는 레거시타입으로 설정된 모델을 의미한다.  Animator가 추가되어 있다면 메카님 애니메이션이다.

애니메이션 클립

애니메이션 클립은 캐릭터의 동작을 기록한 파일입니다. 애니메이션 컴포넌트는 클립에 기록된 관절의 위치와 회전값을 프레임 단위로 재생시키는 역할을 한다.

3D 모델링 툴에서 제작한 애니메이션 클립을 애니메이션 파일로 만드는 방법에는 3가지가 있다.

  • 모든 애니메이션이 하나의 애니메이션 파일에 들어 있고가 있는데 분리 해야하는 경우
  • 모든 애니메이션 클립이 하나의 애니메이션 파일에 들어가 있지만 미리 분리된 경우
  • 애니메이션 클립들이 동작별로 분리해 별도의 파일로 생성하는 방식

애니메이션 적용

애니메이션폴더의 idel을 클릭해서 Inspector뷰를 보면 다음과 같이 아무것도 없다.

씬뷰나 프로젝트뷰의 모델 Player를 끌어다 idel Inspector뷰 맨아리 프리뷰에 끌어다 놓으면 모델이 보인다.

Zoom과 클릭후 Move해서 보기좋게 한후 Play를 누르면 프리뷰를 볼 수 있다.

Player Animation Clip폴더에서 Idel, RunB, RunF, RunL, RunR의 클립만 사용할텐데 Wrap Mode를 Loop로 지정한다. 한꺼번에 할수 없어 개별로 하나씩 해야한다.

하이라키의 Player를 선택한후 자물쇠를 잠구고 Animation Clip폴더에서 Idel, RunB, RunF, RunL, RunR 개를 전부 골라 끌어다 인스펙터의 Animations에 끌어다 놓는다 그럼 오른쪽 숫자가 0에서 5로 바뀐다. 열어보면 5개의 클립이 잘 적용되여 있다. 

이제 처음 실행시킬 Idle 애니메이션을 인스펙터의 Animation에 끌어다 놓으면 None이 Idle로 바뀐다.

설정완료후는 우상쪽 Lock을 푼다. Play해보면 Player가 Idel클립을 반복한다. 한번만 하고 끝난다면 아까 Wrap Mode를Loop로 설정 안한거다.

Player Inspector뷰의 Play Automatically속성은 실행했을때 기본 애니메이션 클립을 자동으로 실행해주는 옵션인데 해제한다. 이러면 play해도 아무런 동작도 하지 않는다.

스크립트를 통해 직접 컨트롤 해보겠다. PlayerCtrl스크립트를 다음과 같이 수정한다.

 

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

public class PlayerCtrl : MonoBehaviour {
    // Start is called before the first frame update
    Transform tr;
    private float moveSpeed;
    private float turnSpeed;
    private Animation anim;
    void Start() {

        tr = GetComponent<Transform>();
        moveSpeed = 10f;
        turnSpeed = 500f;
        anim = GetComponent<Animation>();  //추가된 코드
        anim.Play();
    }

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

        float h = Input.GetAxis("Horizontal");  //AD 입력 좌우
        float v = Input.GetAxis("Vertical");  //WS 입력 전후
        float r = Input.GetAxis("Mouse X");  //마우스 x축 입력
        Vector3 dir = Vector3.right* h + Vector3.forward* v;
        tr.Translate(dir.normalized * moveSpeed * Time.deltaTime);
        tr.Rotate(Vector3.up * turnSpeed * Time.deltaTime * r);
    }
}

Play해 보면게임뷰에서 캐릭터가 Idle동작을 반복해준다.

이제 키보드 동작에 맞춰 애니매이션을 바꿔가면 플레이해보겠다.

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

public class PlayerCtrl : MonoBehaviour {
    // Start is called before the first frame update
    Transform tr;
    private float moveSpeed;
    private float turnSpeed;
    private Animation anim;
    void Start() {
        tr = GetComponent<Transform>();
        moveSpeed = 10f;
        turnSpeed = 500f;
        anim = GetComponent<Animation>();  //추가된 코드
        anim.Play();
    }

    // Update is called once per frame
    void Update() {
        float h = Input.GetAxis("Horizontal");  //AD 입력 좌우
        float v = Input.GetAxis("Vertical");  //WS 입력 전후
        if (Mathf.Abs(h) > float.Epsilon || Mathf.Abs(v) > float.Epsilon) {  //움직임이 없다면 불필요한 동작을 안한다.
            Vector3 dir = Vector3.right * h + Vector3.forward * v;
            tr.Translate(dir.normalized * moveSpeed * Time.deltaTime);
            PlayerAnim(h, v);
        }
        float r = Input.GetAxis("Mouse X");  //마우스 x축 입력 
        tr.Rotate(Vector3.up * turnSpeed * Time.deltaTime * r);

    }
    void PlayerAnim(float h, float v) {
        Debug.Log("Move");
        if (v >= 0.1f) {
            anim.Play("RunF");
        } else if(v <= -0.1f) {
            anim.Play("RunB");
        } else if(h >= 0.1f) {
            anim.Play("RunR");
        } else if (h <= -0.1f) {
            anim.Play("RunL");
        } else {
            anim.Play("Idle");
        }
    }
}

너무 잘된다. 현재도 문제없지만 유니티는 애니메이션사이의 전환을 부드럽게 만들어주는 CroffFade라는 함수를 준비해놓왔다. 사용법은 

CrossFace("클립명", 전환시간);

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

public class PlayerCtrl : MonoBehaviour {
    // Start is called before the first frame update
    Transform tr;
    private float moveSpeed;
    private float turnSpeed;
    private Animation anim;
    void Start() {
        tr = GetComponent<Transform>();
        moveSpeed = 10f;
        turnSpeed = 500f;
        anim = GetComponent<Animation>();  //추가된 코드
        anim.Play();
    }

    // Update is called once per frame
    void Update() {
        float h = Input.GetAxis("Horizontal");  //AD 입력 좌우
        float v = Input.GetAxis("Vertical");  //WS 입력 전후
        if (Mathf.Abs(h) > float.Epsilon || Mathf.Abs(v) > float.Epsilon) {  //움직임이 없다면 불필요한 동작을 안한다.
            Vector3 dir = Vector3.right * h + Vector3.forward * v;
            tr.Translate(dir.normalized * moveSpeed * Time.deltaTime);
            PlayerAnim(h, v);
        }
        float r = Input.GetAxis("Mouse X");  //마우스 x축 입력 
        tr.Rotate(Vector3.up * turnSpeed * Time.deltaTime * r);

    }
    void PlayerAnim(float h, float v) {
        Debug.Log("Move");
        if (v >= 0.1f) {
            anim.CrossFade("RunF",0.25f);
        } else if(v <= -0.1f) {
            anim.CrossFade("RunB", 0.25f);
        } else if(h >= 0.1f) {
            anim.CrossFade("RunR", 0.25f);
        } else if (h <= -0.1f) {
            anim.CrossFade("RunL", 0.25f);
        } else {
            anim.CrossFade("Idle", 0.25f);
        }
    }
}

실행해보면 큰차이를 모르겠지만 동작간 차이가 클 경우 필요할 듯하다.

 

#유니티 #Animation

'유니티게임강좌 > 주인공 캐릭터 제작' 카테고리의 다른 글

[Player제작] 그림자  (0) 2023.02.26
[Player제작] 무기장착  (0) 2023.02.26
[Player제작] 캐릭터 회전 - Rotate  (0) 2023.02.25
Assembly  (0) 2023.02.25
[Player제작] 접근제한자  (0) 2023.02.25

게임오브젝트를 회전시킬 때는 Transform.rotation 속성값을 변경하거나 Rotate계열의 함수를 사용할 수 있다. 

다음은 오브젝트를 y축으로 30도 회전시키는 예이다.

tr.Rotate(new Vector3(0.0f, 30.f, 0.0f);
tr.Rotate(0.0f, 30.0f, 0.0f);
tr.Rotate(Vector3.up * 30f);

마우스입력을 받아 캐릭터가 회전하게 해보겠다. 마우스 움직임이 작기 때문에 스피드가 빨라야 한다.

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

public class PlayerCtrl : MonoBehaviour {
    // Start is called before the first frame update
    Transform tr;
    private float moveSpeed;
    private float turnSpeed;
    void Start() {
        tr = GetComponent<Transform>();
        moveSpeed = 10f;
        turnSpeed = 500f;
    }

    // Update is called once per frame
    void Update() {
        float h = Input.GetAxis("Horizontal");  //AD 입력 좌우
        float v = Input.GetAxis("Vertical");  //WS 입력 전후
        float r = Input.GetAxis("Mouse X");  //마우스 x축 입력
        Vector3 dir = Vector3.right* h + Vector3.forward* v;
        tr.Translate(dir.normalized * moveSpeed * Time.deltaTime);
        tr.Rotate(Vector3.up * turnSpeed * Time.deltaTime * r);
    }
}

씬뷰에서 가상 카메라 이동

씬뷰와 게임뷰를 동시에 표시하고

하이라키에서 Player를 클릭한후 Shift-F를 누르면  Play해보면 씬뷰의 카메라는 Player에 Lock된다.

'유니티게임강좌 > 주인공 캐릭터 제작' 카테고리의 다른 글

[Player제작] 무기장착  (0) 2023.02.26
[Player제작] 애니메이션  (1) 2023.02.26
Assembly  (0) 2023.02.25
[Player제작] 접근제한자  (0) 2023.02.25
[Player제작] 캐릭터의 이동  (0) 2023.02.25

접급제한자 internal을 공부하다가 어셈블리가 나와 유니티 매뉴얼을 보니 같은 라이브러리 같습니다. 유니티는 어셈블리를 관리하는 메뉴가 있네요. 초보분들은 그냥 넘어가는게 나을듯 합니다.

어셈블리 정의

어셈블리 정의 및 어셈블리 레퍼런스는 스크립트를 어셈블리로 구성할 수 있는 에셋입니다.

어셈블리는 스크립트에 의해 정의되고 다른 어셈블리에 대한 레퍼런스도 정의하는 컴파일된 클래스와 구조체가 들어 있는 C# 코드 라이브러리입니다. C#의 어셈블리에 대한 일반적인 정보는 .NET의 어셈블리를 참조하십시오.

기본적으로 Unity는 거의 모든 게임 스크립트를 사전 정의된 어셈블리인 Assembly-CSharp.dll로 컴파일합니다. (또한 Unity는 [몇 가지 더 작고 전문화된 사전 정의 어셈블리]도 생성합니다.)

이 배열은 소규모 프로젝트에 적합하지만, 프로젝트에 코드를 더 추가할 경우 몇 가지 단점이 있습니다.

  • 하나의 스크립트를 변경할 때마다 Unity는 다른 모든 스크립트를 다시 컴파일해야 하므로 반복적 코드 변경을 위한 전체 컴파일 시간이 늘어납니다.
  • 모든 스크립트는 다른 스크립트에서 정의된 타입에 직접 액세스할 수 있으므로 코드를 리팩터링하고 개선하기가 더 어려울 수 있습니다.
  • 모든 스크립트는 모든 플랫폼에 대해 컴파일됩니다.

어셈블리를 정의하면 코드를 구성하여 모듈성과 재사용성을 높일 수 있습니다. 프로젝트에 대해 정의하는 어셈블리의 스크립트는 더 이상 기본 어셈블리에 추가되지 않으며, 지정하는 다른 어셈블리의 스크립트에만 액세스할 수 있습니다.

위 다이어그램은 프로젝트의 코드를 여러 어셈블리로 분할하는 방법을 보여줍니다. Main은 Stuff를 참조하고 그 반대로는 참조하지 않기 때문에 Main의 코드 변경 사항은 Stuff의 코드에 영향을 주지 않습니다. 마찬가지로 Library는 다른 어셈블리에 의존하지 않으므로 다른 프로젝트의 Library에 있는 코드를 더 쉽게 재사용할 수 있습니다.

이 섹션에서는 어셈블리 정의 및 어셈블리 레퍼런스 에셋을 만들고 설정하여 프로젝트에 대해 어셈블리를 정의하는 방법에 대해 설명합니다.

어셈블리 정의

프로젝트 코드를 어셈블리로 구성하려면 원하는 각 어셈블리에 대한 폴더를 생성하고, 각 어셈블리에 속해야 하는 스크립트를 관련 폴더로 옮겨야 합니다. 그런 다음 [어셈블리 정의 에셋을 생성]하여 어셈블리 프로퍼티를 지정하십시오.

Unity는 어셈블리 정의 에셋이 포함된 폴더의 모든 스크립트를 가져온 후 에셋에 정의된 이름 및 기타 설정을 사용하여 어셈블리로 컴파일합니다. 또한 Unity는 자식 폴더에 자체 어셈블리 정의 또는 어셈블리 레퍼런스 에셋이 없는 경우 동일한 어셈블리의 모든 자식 폴더에도 스크립트를 포함합니다.

기존 어셈블리에 자식이 아닌 폴더의 스크립트를 포함하려면 자식이 아닌 폴더에 어셈블리 레퍼런스 에셋을 생성하고, 타겟 어셈블리를 정의하는 어셈블리 정의 에셋을 참조하도록 설정하십시오. 예를 들어 해당 폴더의 위치에 관계없이 프로젝트에 있는 모든 에디터 폴더의 스크립트를 자체 어셈블리에 결합할 수 있습니다.

Unity는 종속성에 의해 결정된 순서대로 어셈블리를 컴파일합니다. 컴파일이 수행되는 순서는 지정할 수 없습니다.

 

레퍼런스 및 종속성

한 타입(예: 클래스 또는 구조체)이 다른 타입을 사용하는 경우 첫 번째 타입은 두 번째 타입에 종속됩니다. Unity가 스크립트를 컴파일할 때 스크립트가 종속되는 모든 타입 또는 기타 코드에 액세스할 수 있어야 합니다. 마찬가지로, 컴파일된 코드가 실행될 때 컴파일된 버전의 종속성에 액세스할 수 있어야 합니다. 두 타입이 서로 다른 어셈블리에 있는 경우 종속 타입을 포함하는 어셈블리는 종속되는 타입을 포함하는 어셈블리에 대한 레퍼런스를 선언해야 합니다.

어셈블리 정의 옵션을 사용하여 프로젝트에 사용된 어셈블리 간의 레퍼런스를 제어할 수 있습니다. 어셈블리 정의 설정에는 다음이 포함됩니다.

  • [Auto Referenced] – 사전 정의된 어셈블리가 어셈블리를 참조하는지 여부
  • [Assembly Definition References] – 어셈블리 정의를 사용하여 생성된 다른 프로젝트 어셈블리에 대한 레퍼런스
  • [Override References] + [Assembly References] – 사전 컴파일된 (플러그인) 어셈블리에 대한 레퍼런스
  • [No Engine References] – UnityEngine 어셈블리에 대한 레퍼런스

참고: 어셈블리 정의를 사용하여 생성된 어셈블리의 클래스는 사전 정의된 어셈블리에서 정의된 타입을 사용할 수 없습니다.

 

기본 레퍼런스

기본적으로 사전 정의된 어셈블리는 어셈블리 정의를 사용하여 생성된 어셈블리(1), 프로젝트에 플러그인으로 추가된 사전 컴파일된 어셈블리(2)를 비롯한 다른 모든 어셈블리를 참조합니다. 또한 어셈블리 정의 에셋을 사용하여 생성된 어셈블리는 모든 사전 컴파일된 어셈블리(3)를 자동으로 참조합니다.

기본 설정의 경우 사전 정의된 어셈블리의 클래스는 프로젝트의 다른 어셈블리에서 정의된 모든 타입을 사용할 수 있습니다. 마찬가지로, 어셈블리 정의 에셋을 사용하여 생성된 어셈블리는 사전 컴파일된 (플러그인) 어셈블리에서 정의된 모든 타입을 사용할 수 있습니다.

어셈블리 정의 에셋에 대한 인스펙터에서 [Auto Referenced 옵션]을 비활성화하여 사전 정의된 어셈블리에서 어셈블리를 참조하지 못하도록 막을 수 있습니다. Auto Referenced 옵션을 비활성화하면 어셈블리에서 코드를 변경할 때 사전 정의된 어셈블리가 다시 컴파일되지 않지만, 사전 정의된 어셈블리가 이 어셈블리의 코드를 직접 사용할 수 없습니다. [어셈블리 정의 프로퍼티]를 참조하십시오.

마찬가지로, 플러그인 에셋에 대한 플러그인 인스펙터에서 Auto Referenced 프로퍼티를 비활성화하여 플러그인 어셈블리가 자동으로 참조되지 못하게 막을 수 있습니다. 이는 사전 정의된 어셈블리, 그리고 어셈블리 정의를 사용하여 생성된 어셈블리 모두에 영향을 미칩니다. 자세한 내용은 플러그인 인스펙터를 참조하십시오.

플러그인 에 대한 Auto Referenced 를 비활성화하면 인스펙터에서 어셈블리 정의 에셋에 대해 명시적으로 레퍼런스를 설정할 수 있습니다. 에셋의 [Override References] 옵션을 활성화하고 플러그인 에 대한 레퍼런스를 추가하십시오. Assembly Definition 프로퍼티를 참조하십시오.

참고: 사전 컴파일된 어셈블리에 대한 명시적 레퍼런스는 선언할 수 없습니다. 사전 정의된 어셈블리는 자동 참조된 어셈블리의 코드만 사용할 수 있습니다.

 

순환 레퍼런스

순환 어셈블리 레퍼런스는 한 어셈블리 레퍼런스가 두 번째 어셈블리를 참조하고, 두 번째 어셈블리는 다시 첫 번째 어셈블리를 참조할 때 존재합니다. 어셈블리 간의 이러한 순환 레퍼런스는 허용되지 않으며, “순환 레퍼런스가 포함된 어셈블리가 감지되었습니다”라는 오류 메시지와 함께 보고됩니다.

일반적으로 어셈블리 간의 이러한 순환 레퍼런스는 어셈블리에서 정의된 클래스 내의 순환 레퍼런스로 인해 발생합니다. 동일한 어셈블리에 있는 클래스 간의 순환 레퍼런스에 대해 기술적으로 유효하지 않은 점은 없지만, 다른 어셈블리의 클래스 간 순환 레퍼런스는 허용되지 않습니다. 순환 레퍼런스 오류가 발생하면 코드를 리팩터링하여 순환 레퍼런스를 제거하거나 상호 참조하는 리팩터링 클래스를 동일한 어셈블리에 배치해야 합니다.

 

어셈블리 정의 에셋 생성

어셈블리 정의 에셋을 만들려면 다음 단계를 따르십시오.

  1. Project 창에서 어셈블리에 포함할 스크립트가 있는 폴더를 찾습니다.
  2. 폴더(메뉴: Assets > Create > Assembly Definition)에 어셈블리 정의 에셋을 생성합니다.
  3. 에셋에 이름을 지정합니다. 기본적으로 어셈블리 파일은 에셋에 할당되는 이름을 사용하지만, Inspector 창에서 이름을 변경할 수 있습니다.

Unity는 프로젝트의 스크립트를 다시 컴파일하여 새로운 어셈블리를 생성합니다. 작업이 완료되면 새로운 어셈블리 정의에 대한 설정을 변경할 수 있습니다.

자식 폴더의 스크립트를 포함하여 어셈블리 정의가 포함된 폴더의 스크립트는 (해당 폴더에 자체 어셈블리 정의 또는 레퍼런스 에셋이 없는 경우) 새로운 어셈블리로 컴파일되고 이전 어셈블리에서 제거됩니다.

 

어셈블리 정의 레퍼런스 에셋 생성

어셈블리 정의 레퍼런스 에셋을 생성하려면 다음 단계를 따르십시오.

  1. Project 창에서 참조된 어셈블리에 포함할 스크립트가 있는 폴더를 찾습니다.
  2. 폴더(메뉴: Assets > Create > Assembly Definition Reference)에 어셈블리 레퍼런스 에셋을 생성합니다.
  3. 에셋에 이름을 할당합니다.
  4. Unity는 프로젝트의 스크립트를 다시 컴파일하여 새로운 어셈블리를 생성합니다. 작업이 완료되면 새로운 어셈블리 정의 레퍼런스에 대한 설정을 변경할 수 있습니다.
  5. 새로운 어셈블리 정의 레퍼런스 에셋을 선택하여 인스펙터 에서 해당 프로퍼티를 확인합니다.
  6. 타겟 어셈블리 정의 에셋을 참조하도록 Assembly Definition 프로퍼티를 설정합니다.
  7. Apply 를 클릭합니다.

자식 폴더의 스크립트를 포함하여 어셈블리 정의 레퍼런스 에셋이 포함된 폴더의 스크립트는 (해당 폴더에 자체 어셈블리 정의 또는 레퍼런스 에셋이 없는 경우) 참조된 어셈블리로 컴파일되고 이전 어셈블리에서 제거됩니다.

 

플랫폼별 어셈블리 생성

특정 플랫폼에 대한 어셈블리를 생성하려면 다음 단계를 따르십시오.

  1. 어셈블리 정의 에셋을 생성합니다.
  2. 새로운 어셈블리 정의 레퍼런스 에셋을 선택하여 인스펙터 에서 해당 프로퍼티를 확인합니다.
  3. Any Platform 옵션을 선택하고 제외할 특정 플랫폼을 선택합니다. 또는 Any Platform을 선택 해제하고 포함할 특정 플랫폼을 선택할 수도 있습니다.
  4. Apply 를 클릭합니다.

플랫폼용 프로젝트를 빌드할 때 어셈블리는 선택된 플랫폼에 따라 포함되거나 제외됩니다.

 

에디터 코드용 어셈블리 생성

에디터 어셈블리를 사용하면 Editor라는 최상위 폴더뿐만 아니라 프로젝트의 모든 위치에 에디터 스크립트를 배치할 수 있습니다.

프로젝트에서 에디터 코드가 포함된 어셈블리를 생성하려면 다음 단계를 따르십시오.

  1. 에디터 스크립트가 포함된 폴더에 [플랫폼별 어셈블리를 생성]합니다.
  2. 에디터 플랫폼만 포함합니다.
  3. 에디터 스크립트가 포함된 추가 폴더가 있는 경우 해당 폴더에 [어셈블리 정의 레퍼런스 에셋을 생성]한 후 이 어셈블리 정의를 참조하도록 설정합니다.

 

테스트 어셈블리 생성

테스트 어셈블리를 사용하면 테스트를 작성하고 Unity TestRunner로 실행할 수 있으며, 테스트 코드를 애플리케이션과 함께 제공하는 코드와 별도로 유지할 수 있습니다. Unity는 테스트 프레임워크 패키지의 일부로 TestRunner를 제공합니다. 테스트 프레임워크 패키지를 설치하고 테스트 어셈블리를 생성하기 위한 지침은 테스트 프레임워크 문서를 참조하십시오.

 

다른 어셈블리 참조

다른 어셈블리의 일부인 C# 타입과 함수를 사용하려면 어셈블리 정의 에셋에서 해당 어셈블리에 대한 레퍼런스를 생성해야 합니다.

어셈블리 레퍼런스를 생성하려면 다음 단계를 따르십시오.

  1. 인스펙터 에서 프로퍼티를 확인하기 위해 레퍼런스가 필요한 어셈블리의 어셈블리 정의를 선택합니다.
  2. Assembly Definition References 섹션에서 + 버튼을 클릭하여 새 레퍼런스를 추가합니다.
  3. 레퍼런스 리스트의 새로 생성된 슬롯에 어셈블리 정의 에셋을 할당합니다.

Use GUIDs 옵션을 활성화하면 새로운 이름을 반영하기 위해 다른 어셈블리 정의의 레퍼런스를 업데이트하지 않고도 참조된 어셈블리 정의 에셋의 파일 이름을 변경할 수 있습니다. (에셋 파일의 메타데이터 파일이 삭제되었거나, Unity 에디터 외부로 파일을 이동할 때 해당 메타데이터 파일을 함께 옮기지 않은 경우 GUID를 초기화해야 합니다.)

 

사전 컴파일된 플러그인 어셈블리 참조

기본적으로 어셈블리 정의를 사용하여 생성된 프로젝트의 모든 어셈블리는 사전 컴파일된 모든 어셈블리를 자동으로 참조합니다. 이러한 자동 참조는 어셈블리의 코드가 사용되지 않더라도 사전 컴파일된 어셈블리 중 하나를 업데이트할 때 Unity가 모든 어셈블리를 다시 컴파일해야 함을 의미합니다. 이러한 추가 오버헤드를 방지하려면 자동 참조를 오버라이드하고 어셈블리가 실제로 사용하는 사전 컴파일된 라이브러리에 대한 참조만 지정하십시오.

  1. 인스펙터 에서 프로퍼티를 확인하기 위해 레퍼런스가 필요한 어셈블리의 어셈블리 정의를 선택합니다.
  2. General 섹션에서 Override References 옵션을 활성화합니다.Override References 를 선택하면 인스펙터  Assembly References 섹션을 이용할 수 있습니다.
  3. Assembly References 섹션에서 + 버튼을 클릭하여 새 레퍼런스를 추가합니다.
  4. 빈 슬롯의 드롭다운 리스트를 사용하여 사전 컴파일된 어셈블리에 레퍼런스를 할당합니다. 리스트에는 프로젝트 빌드 설정에 현재 설정된 플랫폼에 대한 프로젝트의 사전 컴파일된 어셈블리가 모두 표시됩니다. (플러그인 인스펙터에서 사전 컴파일된 어셈블리에 대한 플랫폼 호환성을 설정하십시오.)
  5. Apply 를 클릭합니다.
  6. 프로젝트를 빌드할 각 플랫폼에 대해 이 단계를 반복합니다.

 

조건부 어셈블리 포함

프리 프로세서 심볼을 사용하면 어셈블리가 컴파일되고 게임 또는 애플리케이션의 빌드에 포함되는지 여부를 제어할 수 있습니다(에디터의 플레이 모드 포함). 어셈블리 정의 옵션의 Define Constraints 리스트에서 사용하려는 어셈블리에 대해 정의해야 할 심볼을 지정할 수 있습니다.

  1. 인스펙터 에서 프로퍼티를 확인할 어셈블리의 어셈블리 정의를 선택합니다.
  2. Define Constraints 섹션에서 + 버튼을 클릭하여 제약 리스트에 새로운 심볼을 추가합니다.
  3. 심볼 이름을 입력합니다.
  4. 이름 앞에 느낌표를 붙여서 심볼을 “무효화”할 수 있습니다. 예를 들어 UNITY_WEBGL이 정의되지 않은 경우 !UNITY_WEBGL 제약은 어셈블리를 포함할 수 있습니다.
  5. Apply 를 클릭합니다.

다음 심볼을 제약으로 사용할 수 있습니다.

  • [Scripting Define Symbols] 설정에서 정의된 심볼. 이 심볼은 Project Settings  Player 섹션에서 찾을 수 있습니다. 단, Scripting Define Symbols 는 프로젝트 빌드 설정에서 현재 설정된 플랫폼에만 적용됩니다. 여러 플랫폼에 대한 심볼을 정의하려면 각 플랫폼으로 전환한 후 Scripting Define Symbols 필드를 개별적으로 수정하십시오.
  • Unity에서 정의한 심볼. [플랫폼별 컴파일]을 참조하십시오.
  • 어셈블리 정의 에셋의 [Version Defines] 섹션을 사용하여 정의된 심볼.

스크립트에서 정의된 심볼은 제약이 충족되었는지 판단할 때 고려되지 않습니다.

자세한 내용은 [제약 정의]를 참조하십시오.

 

Unity 및 프로젝트 패키지 버전에 기반하여 기호 정의

프로젝트가 특정한 Unity 버전이나 패키지 버전을 사용하는지에 따라 어셈블리에 다른 코드를 컴파일해야 하는 경우, Version Defines 리스트에 항목을 추가할 수 있습니다. 이 리스트는 기호가 정의되어야 하는 때에 대한 규칙을 지정합니다. 버전 번호에 대해 특정 버전이나 여러 버전으로 평가되는 논리적 표현식을 지정할 수 있습니다.

심볼을 조건부로 정의하려면 다음 단계를 따르십시오.

  1. Inspector 에서 프로퍼티를 볼 어셈블리의 어셈블리 정의 에셋을 선택합니다.
  2. Version Defines 섹션에서 + 버튼을 클릭하여 리스트에 항목을 추가합니다.
  3. 다음 프로퍼티를 설정합니다.
    • Resource: 이 기호를 정의하기 위해 설치해야 하는 패키지나 모듈 또는 Unity 를 선택합니다.
    • Define: 심볼 이름입니다.
    • Expression: 특정 버전 또는 버전 범위로 평가되는 표현식입니다. 규칙은 버전 정의 표현식을 참조하십시오.
    Expression outcome 은 표현식이 어느 버전으로 평가되는지 나타냅니다. 결과에 Invalid 가 표시되면 표현식 구문이 틀린 것입니다.
  4. 다음 예에서는 프로젝트가 Timeline 1.3을 사용하는 경우 USE_TIMELINE_1_3 기호를 정의하며, 프로젝트를 Unity 2021.2.0a7 이상에서 열면 USE_NEW_APIS를 정의합니다.
  5. Apply 를 클릭합니다.

어셈블리 정의에서 정의된 심볼은 해당 정의에 대해 생성된 어셈블리의 스크립트 범위 내에만 있습니다.

Version Defines 리스트를 Define Constraints 로 사용하여 정의된 기호를 사용할 수 있습니다. 따라서 특정 패키지의 특정 버전이 프로젝트에 설치된 경우에만 어셈블리를 사용해야 함을 지정할 수 있습니다.

 

버전 정의 표현식

표현식을 사용하여 정확한 버전이나 여러 버전을 지정할 수 있습니다. Version Define 표현식은 수학적인 범위 표기법을 사용합니다.

대괄호 “[]”는 범위가 엔드포인트를 포함함을 지정합니다.

[1.3,3.4.1]은 1.3.0 <= x <= 3.4.1로 평가됩니다

괄호 “()”는 범위가 엔드포인트를 제외함을 의미합니다.

(1.3.0,3.4)는 1.3.0 < x < 3.4.0으로 평가됩니다

단일 표현식에서 범위 타입을 혼합할 수 있습니다.

[1.1,3.4)는 1.1.0 <= x < 3.4.0으로 평가됩니다

(0.2.4,5.6.2-preview.2]는 0.2.4 < x <= 5.6.2.-preview.2로 평가됩니다

대괄호 안에 단일 버전 지정자를 사용하여 정확한 버전을 지정할 수 있습니다.

[2.4.5]는 x = 2.4.5로 평가됩니다

좀 더 빠른 방법으로는 범위 대괄호 없이 단일 버전을 입력하여 표현식에 해당 버전 이상이 포함되어 있음을 나타낼 수 있습니다.

2.1.0-preview.7은 x >= 2.1.0-preview.7로 평가됩니다

참고: 표현식에서는 공백이 허용되지 않습니다. 와일드카드 문자는 지원되지 않습니다.

Unity 버전 번호

Unity의 현재 버전(및 어셈블리 정의를 지원하는 모든 버전)은 MAJOR.MINOR.REVISION의 세 부분으로 나뉜 버전 지정자(예: 2017.4.25f1, 2018.4.29f1, 2019.4.7f1)를 사용합니다.

  • MAJOR 버전은 타겟 출시년도입니다(예: 2017년, 2021년).
  • MINOR 버전은 타겟 출시 사분기(예: 1분기, 2분기, 3분기, 4분기)입니다.
  • REVISION 지정자는 세 부분으로 나뉘며, 형식은 RRzNN입니다.
    • RR은 1자리 또는 2자리의 개정 번호입니다.
    • z는 출시 유형을 지정하는 글자입니다.
      • a = 알파 출시
      • b = 베타 출시
      • f = 일반 공개 출시
      • c = 중국 출시 버전(f와 동등)
      • p = 패치 출시
      • x = 실험적 출시
    • NN은 1자리 또는 2자리의 번호로, 나중 출시일수록 커집니다.

출시 유형 지정자의 비교 관계는 다음과 같습니다.

a < b < f = c < p < x

즉, 알파 출시는 베타 출시보다 빠르며, 베타 출시는 일반(f) 출시 또는 중국(c) 출시보다 빠릅니다. 패치 출시는 항상 개정 번호가 같은 일반 출시나 중국 출시보다 늦으며, 실험적 개정 번호는 여타 출시 유형보다 늦습니다. 실험 출시는 끝에 나중 출시일수록 커지는 번호를 사용하지 않습니다.

Unity 버전 번호는 REVISION 컴포넌트 뒤에 2019.3.0f11-Sunflower와 같은 접미사 사용이 허용됩니다. 버전 비교 시 접미사는 무시됩니다.

예를 들어, 다음 표현식은 Unity의 모든 2017 또는 2018 버전을 포함하지만, 2019 이상 버전은 일체 포함하지 않습니다.

[2017,2019)

패키지 및 모듈 버전 번호

패키지 및 모듈 버전 지정자는 MAJOR.MINOR.PATCH-LABEL의 유의적 버전 형식을 따르는 네 부분으로 나뉩니다. 처음 세 부분은 항상 숫자이지만, 레이블은 스트링입니다. 프리뷰 상태의 Unity 패키지는 preview 또는 preview.n이라는 스트링을 사용하며, 여기서 n > 0입니다. 패키지 버전 번호에 대한 자세한 내용은 패키지 버전을 참조하십시오.

예를 들어, 다음 표현식은 MAJOR.MINOR 버전이 3.2 - 6.1(포함)인 모든 패키지 버전을 포함합니다.

[3.2,6.1]

 

스크립트가 속한 어셈블리 찾기

C# 스크립트 중 하나가 컴파일되는 어셈블리를 식별하려면 다음 단계를 따르십시오.

  1. Unity Project 창에서 C# 스크립트 파일을 선택하여 Inspector 창에서 해당 프로퍼티를 확인합니다.
  2. 어셈블리 파일 이름과 어셈블리 정의(존재하는 경우)는 Inspector  Assembly Information 섹션에 표시됩니다.

이 예제에서 선택한 스크립트는 Unity.Timeline.Editor 어셈블리 정의 에셋에서 정의된 라이브러리 파일인 Unity.Timeline.Editor.dll로 컴파일됩니다.

 

특수 폴더

Unity는 폴더 내에서 특정한 특수 이름이 지정된 스크립트를 다른 폴더의 스크립트와 다르게 취급합니다. 단, 이러한 폴더는 해당 폴더 내 또는 상위 폴더에 어셈블리 정의 에셋을 생성하면 더 이상 다르게 취급되지 않습니다. 이와 같은 변화는 Editor 폴더를 사용할 때 가장 잘 알아볼 수 있는데, 이러한 Editor 폴더는 보통 코드 정리 방식 과 사용하는 에셋 스토어 패키지에 따라 프로젝트 전체에 걸쳐 분산되어 있습니다.

보통 Unity는 이름이 Editor인 폴더의 모든 스크립트를 이러한 스크립트의 위치와는 상관없이 사전 정의된 Assembly-CSharp-Editor 어셈블리에 컴파일합니다. 단, 하위 폴더 중 Editor 폴더가 있는 폴더에 어셈블리 정의 에셋을 생성하면 해당 에디터 스크립트가 사전 정의된 에디터 어셈블리가 아닌 어셈블리 정의에 의해 생성된 새로운 어셈블리로 전송됩니다. 이 위치는 잘못된 위치입니다. Editor 폴더를 관리하기 위해 각 Editor 폴더에서 어셈블리 정의 또는 레퍼런스 에셋을 생성하고 해당 스크립트를 하나 이상의 에디터 어셈블리에 배치할 수 있습니다. [에디터 코드용 어셈블리 생성]을 참조하십시오.

 

어셈블리 속성 설정

어셈블리 속성을 사용하여 어셈블리에 대한 메타데이터 프로퍼티를 설정할 수 있습니다. 일반적으로 어셈블리 속성 문은 AssemblyInfo.cs 파일에 저장됩니다.

예를 들어 다음 어셈블리 속성은 몇 가지 .NET 어셈블리 메타데이터 값, InternalsVisibleTo 속성(테스트 작업 시 유용), 그리고 프로젝트를 빌드할 때 미사용 코드를 제거하는 방식에 영향을 주는 Unity 정의 [Preserve 속성]을 지정합니다.

[assembly: System.Reflection.AssemblyCompany("Bee Corp.")]
[assembly: System.Reflection.AssemblyTitle("Bee's Assembly")]
[assembly: System.Reflection.AssemblyCopyright("Copyright 2020.")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("UnitTestAssembly")]
[assembly: UnityEngine.Scripting.Preserve]

 

빌드 스크립트에서 어셈블리 정보 가져오기

UnityEditor.Compilation 네임스페이스에서 CompilationPipeline 클래스를 사용하면 Unity가 프로젝트를 위해 빌드한 모든 어셈블리에 대한 정보를 검색해서 가져올 수 있습니다. 여기에는 어셈블리 정의 에셋에 기반하여 생성된 어셈블리도 포함됩니다.

예를 들어 다음 스크립트는 CompilationPipeline 클래스를 사용하여 프로젝트의 모든 현재 플레이어 어셈블리를 나열합니다.

using UnityEditor;
using UnityEditor.Compilation;
public static class AssemblyLister
{
    [MenuItem("Tools/List Player Assemblies in Console")]
    public static void PrintAssemblyNames()
    {
        UnityEngine.Debug.Log("== Player Assemblies ==");
        Assembly[] playerAssemblies =
            CompilationPipeline.GetAssemblies(AssembliesType.Player);

        foreach (var assembly in playerAssemblies)
        {
            UnityEngine.Debug.Log(assembly.name);
        }
    }
}

C# 클래스나 변수를 선언할때 다음과 같은 접근 제한자가 있다.

  • public : 외부클래스(스크립트)에서 접근가능, 인스펙터에 노출됨
  • private : 동일클래스에서만 접근가능. 외부접근 불가, 인스펙터에 노출안됨
  • protected: private과 동일하게 외부접근 불가능하고 상속받은 파생 클래스에서만 접근가능
  • internal : 같은 어셈블리에서만 접근가능. class의 경우 접근제한자를 생략하면 internal이 기본값으로 설정

액세스 한정자는 멤버 또는 형식의 선언된 접근성을 지정하는데 사용되는 키워드

키워드 접근성
public 제한 없음
protected 포함 및 파생
internal 동일 어셈블리로 제한
protected internal 동일 어셈블리 또는 다른 어셈블리여도 포함하는 클래스에서 파생된 형식
private 포함
private protected 포함 or 동일 어셈블리 내의 포함하는 클래스의 파생 ( C# 7.2 이상 )

* 네임 스페이스에는 액세스 한정자가 허용되지 않음 

public class A { }
// 동일 어셈블리에서는 internal만 사용할 경우 public과 접근 제어 수준이 동일함
internal class B { } 

// protected, protected internal, private, private protected는 namespace에는 허용되지 않기 때문에 에러
protected class C { }

* 멤버 선언이 발생한 구문에 따라 특정 액세스 한정자만 허용

- 멤버가 다른 형식 내에 중첩되면 해당 엑세스 가능 영역은 엑세스 가능성 수준 및 한 수준 위 형식의 엑세스 가능 영역에 의해 결정됨

public class A{
    private class AA {
		public int x;
    }
}

public class B {
    void Test() {
        // AA Class가 private 이기 때문에 AA.x가 public 이여도 외부에서 접근할 수 없음
        A.AA aa = new A.AA();
    }
}

* 기본 멤버 액세스 가능성 및 멤버의 허용된 액세스 가능성

구문 기본 멤버 엑세스 멤버의 허용된 액세스
enum public none
class  private  public / protected / internal / private / protected internal, private protected
interface public public / protected / internal / *private ( 기본 구현 필요 ) / protected internal, private protected
struct private 상속이 안되기 때문에 protected는 제외됨

public / internal / private 

* protected

class A
{
    protected int x = 1;
}

class B : A
{
    void Start()
    {
        A a = new A();
        B b = new B();

        // x에 접근할 수 없기 때문에 에러
        a.x = 1;

        // x에 접근할 수 있기 때문에 정상
        x = 2;
    }
}

* internal

// EveryDayDevup-Framework 어셈블리
// 같은 어셈블리에서는 접근이 가능
internal class A {
    public static int x = 1;
}

class C{
    void Test() {
		A.x = 2;
    }
}


// Assembly-CSharp
class B {
    void Start() {
    	// 어셈블리가 다르기 때문에 A에 접근할 수 없음 
        A.x = 3;
    }
}
// internal class를 public으로 변경하고 멤버를 internal로 변경
public class A
{
	internal static int x = 1;
}

class C
{
	void Test()
    {
		A.x = 2;
    }
}


class B : 
{
    void Start()
    {
        A a = new A();
    	// 인스턴스 생성은 가능하지만
        // internal로 설정한 x에 접근할 수 없음 
        a.x = 2;
    }
 }

* protected internal

// EveryDayDevup-Framework
// 같은 어셈블리에 있는 C는 A.x의 접근할 수 있음
public class A
{
	internal int x = 1;
}

public class C 
{
	void Test()
    {
		x = 3;
    }
}

// Assembly-CSharp
// 다른 어셈블리에 있는 B클래스는 상속을 해도 A.x의 접근할 수 없음
class B : A
{
    void Start()
    {
        x = 2;
    }
}
// EveryDayDevup-Framework
// protected internal을 사용하면 다른 어셈블리의 파생 클래스에서 x의 접근이 가능
// protected internal은 멤버에만 사용할 수 있음
public class A
{
	protected internal int x = 1;
}

// Assembly-CSharp
class B : A
{
    void Start()
    {
     	// protected internal은 상속 시 다른 어셈블리에서 접근이 가능
        x = 2;
    }
}

* private

class A
{
    private int x;
    
    public int GetX() {
    	return x;
    }
}

class B
{
    void Test()
    {
        A a = new A();
        // private는 선언된 클래스 또는 구조체의 본문에서만 접근 가능
        // a.x의 접근할 수 없기 때문에 에러
        a.x;
        
        // A에서 x를 접근할 수 있도록 해줘야함
        a.GetX();
    }
}

* private protected

// EveryDayDevup-Framework
// 동일 어셈블리의 파생 클래스에서는 접근이 가능
public class A {
	private protected int x = 1;
}

public class C : A{
	void Test() {
		x = 2;
    }
}

// Assembly-CSharp
class B : A {
    void Test(){
    	// 다른 어셈블리에서는 상속을 받아도 x에 접근할 수 없음 
        x = 3;
    }
}

 

'유니티게임강좌 > 주인공 캐릭터 제작' 카테고리의 다른 글

[Player제작] 캐릭터 회전 - Rotate  (0) 2023.02.25
Assembly  (0) 2023.02.25
[Player제작] 캐릭터의 이동  (0) 2023.02.25
[Player제작] InputManager  (2) 2023.02.25
[Player제작] 유니티 Class 종류  (0) 2023.02.25

Vector3는 UnityEngine 구조체이다

쉽게 생각하면 다음과 같다  물론 실제는 좀더 복잡하다.

public struct Vector3 :IEquatable<Vector3>, IFormattable{
    public float x;
    public float y;
    public float z;
    public static Vector3 right {get;}
    public static Vector3 left {get;}
    public static Vector3 up {get;}
    public static Vector3 down {get;}
    public static Vector3 foward {get;}
    public static Vector3 back {get;}
}
 

이 구조는 Unity 전체에서 3D 위치와 방향을 전달하는 데 사용됩니다. 또한 일반적인 벡터 연산을 수행하기 위한 함수도 포함되어 있습니다.

아래 나열된 함수 외에도 다른 클래스를 사용하여 벡터와 점을 조작할 수도 있습니다. 예를 들어 Quaternion 및 Matrix4x4 클래스는 벡터와 점을 회전하거나 변환하는 데 유용합니다.

 

정적 변수

back Vector3(0, 0, -1) 작성에 대한 약어.
down Vector3(0, -1, 0) 작성에 대한 약어.
forward Vector3(0, 0, 1) 작성에 대한 약어.
left Vector3(-1, 0, 0) 작성에 대한 약어.
negativeInfinity Vector3( float.NegativeInfinity , float.NegativeInfinity , float.NegativeInfinity )
one Vector3(1, 1, 1) 작성에 대한 약어.
positiveInfinity Vector3( float.PositiveInfinity , float.PositiveInfinity , float.PositiveInfinity )
right Vector3(1, 0, 0) 작성에 대한 약어.
up Vector3(0, 1, 0) 작성에 대한 약어.
zero Vector3(0, 0, 0) 작성에 대한 약어.

변수

magnitude 이 벡터의 길이를 반환합니다(읽기 전용).
normalized 크기가 1인 이 벡터를 반환합니다(읽기 전용).
sqrMagnitude 이 벡터의 제곱 길이를 반환합니다(읽기 전용).
this[int] 각각 [0], [1], [2]를 사용하여 x, y, z 구성 요소에 액세스합니다.
x 벡터의 X 구성요소.
y 벡터의 Y 구성 요소입니다.
z 벡터의 Z 구성 요소입니다.

생성자

Vector3 지정된 x, y, z 구성 요소로 새 벡터를 만듭니다.

Public 함수

Equals 주어진 벡터가 이 벡터와 정확히 같으면 true를 반환합니다.
Set 기존 Vector3의 x, y 및 z 구성요소를 설정합니다.
ToString 이 벡터에 대해 형식이 지정된 문자열을 반환합니다.

Static 함수

Angle 및에서 벡터 사이의 각도를 계산합니다.
ClampMagnitude maxLength 로 고정된 벡터의 복사본을 반환합니다 .
Cross 두 벡터의 외적.
Distance a와 b 사이의 거리를 반환합니다.
Dot 두 벡터의 내적.
Lerp 두 점 사이를 선형 보간합니다.
LerpUnclamped 두 벡터 사이를 선형 보간합니다.
Max 두 벡터의 가장 큰 구성 요소로 만들어진 벡터를 반환합니다.
Min 두 벡터의 가장 작은 구성 요소로 만들어진 벡터를 반환합니다.
MoveTowards maxDistanceDelta 로 지정된 거리보다 더 멀리 이동하지 않고 현재 및 대상으로 지정된 점 사이의 위치를 계산합니다 .
Normalize 이 벡터의 크기를 1로 만듭니다.
OrthoNormalize 벡터를 정규화하고 서로 직교하도록 만듭니다.
Project 벡터를 다른 벡터에 투영합니다.
ProjectOnPlane 평면에 수직인 법선으로 정의된 평면에 벡터를 투영합니다.
Reflect 법선에 의해 정의된 평면에서 벡터를 반사합니다.
RotateTowards 대상을 향해 벡터 전류를 회전합니다.
Scale 두 벡터를 구성요소별로 곱합니다.
SignedAngle 축을 기준으로 시작과 끝 벡터 사이의 부호 있는 각도를 계산합니다.
Slerp 두 벡터 사이를 구면으로 보간합니다.
SlerpUnclamped 두 벡터 사이를 구면으로 보간합니다.
SmoothDamp 시간이 지남에 따라 원하는 목표를 향해 벡터를 점차적으로 변경합니다.

operator - 한 벡터에서 다른 벡터를 뺍니다.
operator != 벡터가 다른 경우 true를 반환합니다.
operator * 벡터에 숫자를 곱합니다.
operator / 벡터를 숫자로 나눕니다.
operator + 두 벡터를 더합니다.
operator == 두 벡터가 거의 같으면 true를 반환합니다.

 

'유니티스크립팅 > 유니티매뉴얼' 카테고리의 다른 글

카메라 - 유니티  (0) 2023.03.03
마우스좌표를 월드좌표로 - 2D  (0) 2023.03.02
[유니티매뉴얼] Unity의 회전 및 방향  (0) 2023.02.28
변수와 함수  (0) 2023.02.25
Scripts as Behaviour Components  (0) 2023.02.25

+ Recent posts