

: 가장 먼저 1번 실행되는 함수
: 오브젝트가 on될 때마다 1번 실행되는 함수
: 1번 실행되는 함수
: 오브젝트가 off될 때마다 1번 실행되는 함수
: 오브젝트가 파괴될때 1번 실행되는 함수
: 고정된 프레임마다 계속 실행
: 컴퓨터 성능에 따라 계속 실행
: Update 다음에 실행
: 두 오브젝트가 충돌했을 때 1번 호출
: 두 오브젝트가 충돌 상태를 유지하는 동안 호출
: 두 오브젝트가 충돌 상태에서 벗어났을 때 호출
: Collider 영역에 들어갔을 때 1번 호출
: Collider 영역에 들어간 상태를 유지하는 동안 호출
: Collider 영역을 벗어났을 때 1번 호출

: 마우스로 누를 때 1번 실행
: 마우스로 뗄 때 1번 실행
: 마우스 포인터가 진힙했을 때 1번
: 마우스로 포인터가 빠져나갔을 때 1번
: 마우스 오브젝트 위에 있을 때 계속 실행
: 마우스를 누른 상태로 있을 때 계속 실행
: 오브젝트 범위 내에서 마우스를 뗀 경우 1번 실행
: 키를 누르고 있는 동안 계속 실행
: 키를 누른 순간 1번 실행
: 키를 뗀 순간 1번 실행
: 입력값을 -1~1값으로 변환
: 보정 없는 즉기 값 변환 (-1.0.1)
: 아무 키나 눌렀을 때 true
: 아무 키나 처음 눌렀을 때 1번
: 조건의 결과를 보고 실행되는 문법
if (조건 A){
조건 A가 true
}
else if(조건 B){
조건 B가 true
}
else{
그 외의 경우
}
switch (변수)
{
case a:
break;
//변수가 a일경우 실행
case b:
break;
//변수가 b일경우 실행
case c:
break;
//변수가 c일경우 실행
default:
break;
//변수의 값이 위의 값 이외의 경우 실행
}
: 호출 함수
: 지연시간 후 함수 실행
: 지연시간 후 함수 실행 한 후 반복주기 마다 실행
ex) InvokeRepeating("함수명",3f, 2f) -> 함수를 3초 후에 실행한 후 2초마다 반복 실행
: 호출한 Invoke함수 취소 (Invoke,InvokeRepeating으로 예약된 호출만 취소가능)
Invoke("함수명", 지연시간);
InvokeRepeating("함수명", 처음 지연시간, 반복주기);
CancelInvoke("함수명");
: 조건에 만족하면 반복해서 실행되는 문법
: 조건이 성립되는 동안 반복
while (조건 A){
조건 A가 true인 경우 실행
}
: do -> while 조건 확인 -> do -> while 조건 확인 -> do ...
: 조건에 맞지 않아도 do문은 한번 실행
do
{
}
while(조건 A)
: 순차적으로 반복
for(변수 정의; 반복범위; 증감단위){
}
for( i = 1; i < 3 ; i++){
Debug.Log(i);
}
: 배열이나 리스트를 하나씩 반복
foreach(데이터타입 변수 in Collection){
}
private string[] personNames = ["철수","영희","영지"];
foreach(var personName in personNames){
Debug.Log(personName);
}
철수
영희
영지
break : 반복문을 빠져나오는 기능
return : 함수를 종료
continue : continue보다 아래 기능을 실행하지 않고 다시 반복문을 실행
: Random.Range(int or float a, int or float b)
: a~b까지의 랜덤 숫자 뽑기
(시작 시간과 끝나는 시간이 정해져있을때 사용, 느린판단을 할때)
yield return null; -> 1프레임 대기 Update 호출까지 대기 후 실행
yield return new WaitForFixedUpdated(); -> FixedUpdate 호출까지 대기 후 실행
yield return new WaitForSeconds(time); -> tiem 만큼 대기 후 실행
yield return new WaitForSecondsRealtime(time); -> Timescale에 영향 X, time 대기 후 실행
yield return new WaitForEndOffFrame(); -> 모든 렌더링 작업이 완료될 때까지 대기 후 실행
yield return new WaitUntill(()=>time > 10); -> 해당 조건이 true가 될때까지 대기 후 실행
yield break; -> 코루틴 종료
//함수 호출 방법
void Start(){
StartCoroutine("Routine");
StartCoroutine(nameof(Routine));
StartCoroutine(Routine());
//매개변수 한개(함수 이름으로 실행할 경우)
StartCoroutine("Routine1",4);
//매개변수 여러개(함수 자체로 실행)
StartCoroutine(Rotuine2(1,2,3));
}
//코루틴 생성 방법
IEnumerator Routine(){
Debug.Log("Hello");
yield return new WaitForSeconds(3f);
}
IEnumerator Routine1(int a){
Debug.Log("a");
yield return null;
}
IEnumerator Routine2(int a, int b, int c){
Debug.Log("a");
Debug.Log("b");
Debug.Log("c");
yield return null;
}
//함수 종료 방법
private Coroutine runningCoroutine; -> 반환값 Coroutine을 담을 맴버 변수 선언
void Start()
{
runningCoroutine = StartCoroutine(Running());
Invoke("StopRoutine", 1.5f);
}
IEnumerator Running()
{
Debug.Log("실행 1");
yield return new WaitForSeconds(1.0f);
Debug.Log("실행 2");
yield return new WaitForSeconds(1.0f);
Debug.Log("실행 3");
yield return new WaitForSeconds(1.0f);
}
private void StopRoutine()
{
StopCoroutine(runningCoroutine); -> StopCoroutine(Running())은 작동하지 않는다.
Debug.Log("강제 종료");
StopAllCoroutines(); // 클래스 내에서 실행되는 모든 Coroutine 정지
}
: 데이터 타입을 파라미터로 활용하는 변수
public void Copy(int[] source, int[] target)
{
for (int i = 0 ; i < source.Length ; i++)
{
target[i] = source[i];
}
}
public void Copy(float[] source, float[] target)
{
for (int i = 0 ; i < source.Length ; i++)
{
target[i] = source[i];
}
}
public void Copy<T>(T[] source, T[] target) -> 일반화(모든 자료형 사용 가능->호출 시 자료형 재정의)
{
for (int i = 0 ; i < source.Length ; i++)
{
target[i] = source[i];
}
}
//오브젝트 풀 예시 문
public class ObjectPool<T> where T : Component -> 제약 조건(T타입에 대한 조건 지정)
{
private Queue<T> pool = new Queue<T>();
private T prefab;
public ObjectPool(T prefab, int initialCount)
{
this.prefab = prefab;
for(int i = 0; i <initialCount ; i++)
{
T obj = GameObject.Instantiate(prefab);
obj.gameObject.SetActive(false);
pool.Enqueu(obj);
}
}
public T Get()
{
if(pool.Count > 0)
{
var obj = pool.Dequeue();
obj.gameObject.SetActive(true);
return obj;
}
return GameObject.Instantiate(prefab);
}
public void Return(T obj)
{
obj.gameObject.SetActive(false);
pool.Enqueue(obj);
}
}
public int num = 10;
void Start()
{
NormalParameter(num);
RefParameter(ref num);
}
public void NormalParameter(int n)
{
Debug.Log("호출 전 : " + n);
n = 1;
Debug.Log("호출 후 : " + num);
}
public void RefParameter(ref int n)
{
Debug.Log("호출 전 : " + n);
n = 1;
Debug.Log("호출 후 : " + num);
}
호출 전 : 10
호출 후 : 10 -> 원본이 변경 X
호출 전 : 10
호출 후 : 1 -> ref는 원본이 변경되었다.
public class OutParameter : MonoBehaviour
{
void Start()
{
int a = Random.Range(1,100);
int b = Random.Range(1,100);
//Old 버전
int result1 = 0;
int result2 = 0;
Divide(a,b,out result1,out result2);
//Out 파라미터를 메소드를 호출할 때 선언 가능
//현재 메소드가 호출되는 블록 내부에서 선언 이후 사용 가능
Divide(a,b,out int result1, out int result2);
// var 키워드 사용 가능
// 메소드 정의에는 var를 사용할 수 없기 때문에 메소드 정의를 참고해서 자동 설정
Divide(a, b, out var r1, out var r2);
//메소드 정의는 2개의 out 파라미터를 사용하도록 되어 있지만 필요 없는 경우도 존재 가능 '_' 사용
Divide(a,b,out var rr1, out _);
Debug.Log($"{a} / {b} = {result1}");
Debug.Log($"{a} / {b} = {result2}");
Debug.Log($"{a} / {b} = {r1}");
Debug.Log($"{a} / {b} = {r2}");
Debug.Log($"{a} / {b} = {rr1}");
}
void Divide(int num1, int num2,out int r1,out int r2)
{
r1 = num1 / num2; ->몫
r2 = num1 % num2; -> 나머지
}
}
5 / 2 = 2
5 % 2 = 1
5 / 2 = 2
5 % 2 = 1
5 / 2 = 2
void Like(int x, params string[] message)
{
foreach (string s in message)
{
Debug.Log(s);
}
}
void Start()
{
int x = 3;
Like(x, "맑음","나쁨","바람");
}
3
맑음
나쁨
바람
public int[] nums = {1,2,3,4,5};
void Start()
{
ParamsParameter(1,2,3,4,5);
ParamsParameter(10,20,30);
}
void ParmasParameter(params int[] numbers)
{
string str = "";
foreach (var number in numbers)
{
str += num + " ";
}
Debug.Log(str);
}
1 2 3 4 5
10 20 30
public partial class StudyPartial : MonoBehaviour
{
void Start()
{
Debug.Log("Start method");
}
}
public partial class StudyParital
{
void Update()
{
Debug.Log("Update mehtod");
}
}
Start method
Update method
Update method
Update method
Update method
...
-> 2개의 파일이 컴파일 시 내용이 합쳐져서 하나의 클래스가된다.
Sealed
public class BaseClass : MonoBehaviour
{
public virtual void Method()
{
Debug.Log("일반 함수");
}
}
public class MiddleClass : BaseClass
{
public sealed override void Method()
{
Debug.Log("봉인된 오버라이드 함수");
}
}
public class LastClass : MiddleClass
{
public override void Method() --> 함수가 봉인되었기 때문에 오류 발생(override 불가)
{
Debug.Log("오버라이드 함수");
}
}
: 함수를 참조
접근제한자 delegate 반환타입 이름(매개변수)
public delegate void MyDelegate();
public class StudyDelegate : MonoBehaviour
{
public delegate void MyDelegate();
public MyDelegate onDelegate;
void Start()
{
//onDelegate에 함수 할당
onDelegate = MethodA;
//MethodB 추가
onDelegate += MethodB;
//MethodC 추가
onDelegate += MethodC;
//MethodB 삭제
onDelegate -= MethodB;
//직접 실행
onDelegate();
//직접 실행과 동일한 방식
//delegate.invoke -> 함수 즉시 호출, monobehaviour.invoke -> 지연 호출
onDelegate.Invoke();
//null 체크 방식
OnDelegate?.Invoke();
}
}
public class ParameterDelegate : MonoBehaviour
{
public delegate void MyDelegate(int a = 10); -> 매개변수가 있는 함수 연결(default값을 10으로 설정)
public Mydelegate onDelegate;
void Start()
{
onDelegate += MethodA; -> 오류 발생
onDelegate += MethodB;
}
private void MethodA(){} -> 매개변수가 없는 함수
private void MethodB(int b){} -> 매개변수가 있는 함수
}
public class ExampleEvent : MonoBehaviour
{
//델리게이트정의
public delegate void InputKeyHandler();
// public delegate void InputKeyHandler(string msg);
//event 선언
public event InputKeyHandler onInputKey;
//위에 두줄 == public event Action onInputKey;
public KeyCode keycode = KeyCode.Space;
void start
{
// 구독
onInputKey += OnInputKey;
}
void Update()
{
if (Input.GetKeyDown(keycode)
{
//구독자가 한명이라도 있으면 실행(즉, 0명인지 확인)
onInputKey?.Invoke();
//onInputKey?.Invoke($"{keyCode}를 눌렀습니다");
}
}
public void OnInputKey()
{
Debug.Log("key Down");
}
/*public void OnInputKey(string msg)
{
Debug.Log(msg);
}
*/
}
using UnityEngine.Events; -> UnityEvent를 사용할려면 작성해야함
public class StudyUnityEvent : MonoBehaviour
{
[SerializedField] private void UnityEvent onHappened -> 인스펙터 노출(외부 접근 제한)
public UnityEvent uEvent;
void Start()
{
//구독
uEvent.AddListener(MethoA);
uEvent.AddListener(MethoB);
//매개변수가 있는 함수의 경우
uEvent.AddListener(() => MethodC(10));
//삭제
uEvent.RemoveListener(MethoA);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)
{
//실행
uEvent?.Invoke();
}
}
private void MethodA(){}
private void MethodB(){}
private void MethodC(int num){}
}
public delegate void EventHandler(object sender, EventArgs e);
//object sender -> 이벤트를 실행시키는 객체
//EventArgs e -> 이벤트 실행시 전달할 수 있는 매개변수
public class StudyEventHandler : MonoBehaviour
{
private event EventHandler handler;
//add, remove 이벤트 접근자
public event EventHandler Handler //프로퍼티
{
add
{
Debug.Log($"{value.Method} 추가됨"); -> MethodA 추가됨
handler += value;
}
remove
{
Debug.Log($"{value.Method} 삭제됨"); -> MethodA 삭제됨
handler -= value;
}
}
//EventHandler -> void 타입의 매개변수가 2개인 델리게이트
//delegate의 작업에서 주로 쓰이는 형태 OnEnable <-> OnDisable
//켜져있으면 자동등록
void OnEnable()
{
Handler += MethodA;
}
//파괴되거나 없어지면 구독해제
void OnDisable()
{
Hanbdler -= MethodA;
}
void Update()
{
if(Input.GetKeyDown(keyCode.Space)
handler?.Invoke(this, EventArgs.Empty);
-> 매개변수를 아무것도 넣은게 없다면 (이렇게할거면 다른거를 사용하는게 좋음)
}
public void MethodA(object o, EventArgs e)
{
}
}
public class ExternalClass : MonoBehaviour
{
public StudyEventHandler study;
void Start()
{
study?.Invoke(this, EventArgs.Empty); -> 실행불가능
}
}
public class DataClass : EventArgs
-> Invoke를 통해 핸들러를 실행했을 때 데이터클래스의 정보를 활용하고 싶으면 DataClass에 EventArgs를 상속시키면 된다.
{
public string dataName;
public int dataNumer;
public bool isData;
public DataClass(string dataName, int dataNumber, bool isData)
{
this.dataName = dataName;
this.dataNumber = dataNumber;
this.isData = isData;
}
}
public class StudyEventHandler : MonoBehaviour
{
public event EventHandler handler;
-> EventHandler는 여러 데이터를 활용하는 용도로 사용
void Start()
{
handler += StartEvent;
DataClass data1 = new DataClass("DataClass1",1,false);
DataClass data1 = new DataClass("DataClass1",1,false);
handler?.Invoke(this , data1); -> (data1을 Eventargs타입인 e로 자동변환 -> 업캐스팅)
handler?.Invoke(this , data2);
}
private void StartEvent(object o, EventArgs e)
{
var data = (DataClass)e; -> 형변환(e를 DataClass형태로 전환 -> 다운캐스팅)
Debug.Log($"Data Name : {data.dataName}");
}
}
업캐스팅, 다운캐스팅 없이 전달하기 위해서 EventHandler<'T'>를 사용
public class StudyEventHandler : MonoBehaviour
{
public event EventHandler<DataClass> handler;
-> 제너릭<T>를 활용
-> delegate void EventHandler<T>(object sender, T e)
void Start()
{
handler += StartEvent;
DataClass data1 = new DataClass("DataClass1",1,false);
DataClass data1 = new DataClass("DataClass1",1,false);
handler?.Invoke(this , data1);
handler?.Invoke(this , data2);
}
private void StartEvent(object o, DataClass e) -> 제너릭<T> 타입을 DataClass로 설정을 했기때문에 EventArgs를 넣을 필요가 없어짐
{
Debug.Log($"Data Name : {e.dataName}");
Debug.Log($"Data Name : {e.dataNumber}");
Debug.Log($"Data Name : {e.isData}");
}
}
public class StudyLamda : MonoBehaviour
{
public delegate void MyDelegate();
public MyDelegate myDelegate;
void Start()
{
//myDelegate = OnLog;
myDelegate = delegate -> 한번 쓰는 함수를 void OnLog(){} 쓰기 귀찮음 -> 일회용 함수 사용(함수 이름 X)
{
Debug.Log("Hello Unity");
}
myDelegate?.Invoke();
//매개변수가 있는 익명함수
//myDelegate += delegate ~ 도 사용 가능
myDelegate = delegate (string s)
{
Debug.Log(s);
}
myDelegate?.Invoke("Hello Unity");
}
/*
public void OnLog()
{
Debug.Log("Hello Unity");
}
*/
}
public class StudyLamda : MonoBehaviour
{
public delegate void MyDelegate1();
public delegate void MyDelegate2(string s);
public delegate void MyDelegate3(string s);
public MyDelegate1 myDelegate1;
public MyDelegate2 myDelegate2;
public MyDelegate2 myDelegate3
void Start()
{
myDelegate1 = () => Debug.Log("Hello Unity");
myDelegate1?.Invoke();
myDelegate2 = (s) => Debug.Log(s);
myDelegate2?.Invoke("Hello Unity");
myDelegate3 = (s) =>
{
Debug.Log(s);
Debug.Log("Hello Unity");
}
myDelegate3?.Invoke("Hello C#");
}
}
Hello Unity
Hello Unity
Hello C#
Hello Unity
public class StudyLamda : MonoBehaviour
{
public Button buttonUI;
void Start()
{
buttonUI.onClick.AddListener( () => OnLog("Hello") );
}
private void OnLog(string msg)
{
Debug.Log("Hello Unity");
}
}
: 외부 함수의 변수를 내부 함수가 참조할 때 발생
-> 내부 함수는 외부 함수의 실행이 끝난 후에도 외부 함수의 변수에 접근 가능
public class ExampleClosure : MonoBehaviour
{
public Button[] buttonUIs;
void Start()
{
for (int i = 0 ; i < 5 ; i++) -> 외부함수의 영역
{
int temp = i; -> Closure 이슈 방지, temp는 매 for문 바퀴마다 새로 생성
buttonUIs[i].onClick.AddListener(() => SetButton(temp)); ->(()=>Setbutton(temp))가 내부함수
}
}
}
: 여러 개의 매개변수를 넣을 수 있고 반환타입이 있는 Delegate
-> 마지막에 적은 타입이 반환타입
접근제한자 Func<매개변수1, 매개변수2, 반환타입> 변수명;
public Func<int, int, int -> 반환타입> myFunc;
public class StudyFunc : MonoBehaviour
{
public Func<int,int,int> myFunc; -> int 반환타입
public Func<string, string, bool> myFunc2; -> bool 반환타입
void Start()
{
myFunc = AddMethod;
int result = myFunc?.Invoke(10,7);
Debug.Log($"최종 결과 : {result}");
myFunc2 = CompareText
bool result =2 myFunc2?.Invoke("hello", "unity");
Debug.Log(result2);
}
private int AddMethod(int num1, int num2)
{
return num1 + num2;
}
public bool CompareText(string msg1, string msg2)
{
if (a==b)
return true;
return false;
}
}
여러 개의 Func를 추가한 List
using System;
using System.Collections.Generic;
using UnityEngine;
public class StudyFunc : MonoBehaviour
{
private List<Func<int, int>> funcList = new List<Func<int, int>>();
void Start()
{
funcList.Add(AddMethod);
funcList.Add(MinusMethod);
funcList.Add(MultiplyMethod);
-> 람다식으로 줄일 수 있음 (addmethod,minusmethod,multiplymethod가 필요없어짐)
funcList.Add(n => n + 1);
funcList.Add(n => n - 3);
funcList.Add(n => n * 2);
int result = 0;
foreach (var func in funcList) -> 함수 순서대로 동작
result += func(5);
Debug.Log($"최종 결과: {result}");
}
private int AddMethod(int n)
{
return n + 1;
}
private int MinusMethod(int n)
{
return n - 3;
}
private int MultiplyMethod(int n)
{
return n * 2;
}
}
18 (addmethod return : 6 + minusmethod return : 2 + multiplymethod return : 10)
: 반환값이 boolean인 Delegate
접근제한자 Predicate<매개변수> 변수명;
public Preicate<int> myPredicate;
public class StudyPreicate : MonoBehaviour
{
public Predicate<int> myPredicate;
public int myLevel = 10;
void Start()
{
myPredicate = n => n <= 10; (n <= 10) -> true 값이 n으로 반환
string msg = myPredicate(myLevel) ? "초보자 사냥터 이용 가능" : ":초보자 사냥터 이용 불가능"; -> 반환값에 따라 ? 이용 가능(true) : 이용 불가능(false)
Debug.Log(msg);
}
}
: 반환 타입이 없는 Delegate
접근제한자 Action 변수명;
접근제한자 Action<매개변수(여러개도 가능)> 변수명;
public class StudyAction : MonoBehaviour
{
//매개변수 없는
public Action myAction;
//매개변수가 있는
public Action<string> myAction2;
void Start()
{
myAction = () => Debug.Log("Hello Unity");
myAction?.Invoke();
myAction2 = (s) => Debug.Log(s);
myAction2?.Invoke("Hello Unity");
}
}
Action은 함수만 static
public class ExampleAction : MonoBehaviour
{
public static Action myAction; -> myActiong만 static
//public static event Action myAction; -> 캡슐화 작업을 통해 외부 작업 방지
// Property는 변수 캡슐화 작업
void Start()
{
myAction += AddMethod;
}
private void AddMethod()
{
Debug.Log("더하는 기능");
}
}
public class ExampleClass : MonoBehaviour
{
void Start()
{
ExampleAction.myAction += OtherMethod; -> 외부에서 실행할때, 굳이 싱글턴 또는 변수만들어서 할 필요없이 static된 myAction만 접근가능
ExampleAction.myAction?.Invoke();
}
public void OtherMethod()
{
Debug.Log("기능");
}
}
: Unity에서 제공하는 Action Delegate
public class StudyUnityAction : MonoBehaviour
{
public Button buttonUI;
public UnityAction uAction;
void Start()
{
uAction += MethodA;
uAction += MethodB;
uAction += MethodC;
buttonUI.onClick.AddListener(uAction);
}
private void MethodA(){};
private void MethodB(){};
private void MethodC(){};
}