사용자가 입력한 키를 이름
으로 식별
Input.GetKey("이름")
사용자가 입력한 키를 KeyCode.열거 매개 변수
로 식별
Input.GetKey(KeyCode.매개변수)
Rocket
오브젝트에 적용할 스크립트 작성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
ProcessThrust();
ProcessRotation();
}
void ProcessThrust()
{
if (Input.GetKey(KeyCode.Space)) // spacebar 누를 경우 아래 코드 출력
{
Debug.Log("Pressed SPACE - Thrusting");
}
}
void ProcessRotation()
{
if (Input.GetKey(KeyCode.A)) // A 누를 경우 아래 코드 출력
{
Debug.Log("Rotating left");
}
// else if : 위 조건이 만족되지 않을시 이 특정 조건이 실행됨
else if (Input.GetKey(KeyCode.D)) // D 누를 경우 아래 코드 출력
{
Debug.Log("Rotating right");
}
}
}
=>A
와 D
를 동시에 누를 경우 조건문 순서로 인해 A
의 구문이 실행된다.
스페이스바를 누르면 로켓이 하늘로 날아 오르도록 만들기
Rocket
에 Rigid Body
(개체에 물리 적용) 추가Movement
스크립트에서 AddRelativeForce()
함수 추가void ProcessThrust()
{
if (Input.GetKey(KeyCode.Space)) // spacebar 누를 경우 아래 코드 출력
{
float force = 5f; // 추가한 뒤 mass 아주 작게 설정해야 실행됨
rb.AddRelativeForce(0f, force, 0f);
// 파라미터는 x, y, z 나타내며, 파라이터 값을 통해 특정 각도로 이동
// 3D 게임 - Vector3로 입력 가능
}
}
Rigidbody
여러 변수들과 Transform
변수 조정오브젝트를 위로 이동시키는 코드
AddRelativeForce(0, 1, 0)
=AddRelativeForce(Vector3.up)
mainThrust
Time.deltaTime
[SerializeField] float mainThrust = 1000f;
.
.
.
void ProcessThrust()
{
if (Input.GetKey(KeyCode.Space)) // spacebar 누를 경우 아래 코드 출력
{
Debug.Log("Press Space");
rb.AddRelativeForce(Vector3.up * mainThrust * Time.deltaTime);
//위로 향하는 추진력 변수 mainThrust
// 프레임률 영향을 받지 않도록 하는 Time.deltaTime
}
}
transform.Rotate()
함수 추가[SerializeField] float rotationThrust = 1f;
.
.
.
void ProcessRotation()
{
if (Input.GetKey(KeyCode.A)) // A 누를 경우
{
transform.Rotate(Vector3.forward * rotationThrust * Time.deltaTime); // 앞 : Z방향
}
// else if : 위 조건이 만족되지 않을시 아래 조건 실행
else if (Input.GetKey(KeyCode.D)) // D 누를 경우
{
transform.Rotate(-Vector3.forward * rotationThrust * Time.deltaTime); // 뒤 : -Z방향
}
}
ApplyRotation
생성ctrl + .
- Extract method/메서드 추출
: 메서드 생성public
(공용 메서드) : 다른 클래스에서도 이 메서드를 불러올 수 있음private
(사설 메서드) : 오직 그 사설 메서드를 가진 클래스만 이 메서드에 접근, 호출, 변경, 수정할 수 있다. public이 존재할 경우 나머지 변수들이 private이라는 사실이 기정사실화되므로 대부분 생략한다.Z
, -Z
) 출력값 다르게 할 것 void ProcessRotation()
{
if (Input.GetKey(KeyCode.A)) // A 입력받을 경우
{
ApplyRotation(rotationThrust); // Z값 넘김
}
// else if : 위 조건이 만족되지 않을시 이 특정 조건이 실행됨
else if (Input.GetKey(KeyCode.D)) // D 입력받을 경우
{
ApplyRotation(-rotationThrust); // -Z값 넘김
}
}
private void ApplyRotation(float rotationThisFrame)
{
transform.Rotate(Vector3.forward * rotationThisFrame * Time.deltaTime);
}
Error
Hierarchy에서 object가 선택되고 play하면 이상하게 movement가 예상대로 작동하질 않았다. (mass가 엄청난 것처럼) 알아보니 옛날 버전 unity의 이상한 버그라고 한다. 해당 object를 선택하지 않고 play할 경우 에러는 해결되었다.
Movement.cs
에서 수동 제어 코드 부분 수정void ApplyRotation(float rotationThisFrame)
{
rb.freezeRotation = true; // freezing rotation so we can manually rotate
transform.Rotate(Vector3.forward * rotationThisFrame * Time.deltaTime); // 수동 제어 : 강제로 특정 방향으로 회전하라고 지시
rb.freezeRotation = false; // unfreezing rotation so the physics system can take over
}
Rigidbody
- Drag
설정Edit
- Project Settings
- Physics
- Gravity
(x, y, z 방향 모두 설정 가능)
Main Camera의 Inspector에 존재
오디오를 생성하는 object에 추가
현재 방법은 object가 단 하나의 소리를 낸다는 가정하에 진행하는 방법이다. (만약 여러 소리를 내야한다면 다른 방식을 사용해야한다.)
오디오 클립 받는 방법
※ 효과음 파일을 찾거나 직접 녹음을 한다면 Ogg
나 MP3
사용
다운 받은 클립을 rocket Audio Source
의 Audio Clip
에 넣어준다.
오디오 겹침 현상 해결
AudioSource audioSource; // 참조 캐싱
// 생략 //
void ProcessThrust()
{
if (Input.GetKey(KeyCode.Space)) // spacebar 누를 경우 아래 코드 출력
{
// float force = 5f;
rb.AddRelativeForce(Vector3.up * mainThrust * Time.deltaTime); // 3D 게임이므로 Vector3 (x, y, z) 입력 / x 1유닛, y 1유닛, z 1유닛씩 이동해서 특정 각도로 이동
if(!audioSource.isPlaying) // 재생하고 있지 않을 때만 재생 (오디오가 겹치지 않기 위해)
{
audioSource.Play(); // 오디오 소스에 추가한 오디오 클립 재생
}
}
else // 로켓이 추진하지 않을 경우
{
audioSource.Stop(); // 오디오 정지
}
}
// 생략 //
Audio Source
의 Play On Awake
체크 해제충돌 시스템 구현
충돌 관련 object : tag
설정
CollisionHandler.cs
- Switch문 구현
Switch문
- If나 Else문같은 조건문
- 하나의 변수와 비교할 수 있게 해준다.
- switch 문법
switch (variableToCompare) // 변수 = 충돌한 객체의 태그 { case valueA: ActionToTake(); break; case valueB: OtherAction(); break; default: YetAnotherAction(); break; }
충돌 결과
다른 object에 충돌시 처음부터 다시시작
File
- Build Settings
- Add Open Scenes
CollisionHandler.cs
편집using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionHandler : MonoBehaviour
{
void OnCollisionEnter(Collision other) // 부딪힌 다른 것이 무엇인지 물어보는 것
{
switch(other.gameObject.tag)
{
case "Friendly":
Debug.Log("This thing is friendly");
break;
case "Finish":
Debug.Log("Congrats, yo, you finished!");
break;
case "Fuel":
Debug.Log("You picked up fuel");
break;
default:
ReloadLevel();
break;
}
}
void ReloadLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex; // buildIndex : 현재 활동하고 있는, 빌드 설정에 있는 씬의 인덱스 반환
SceneManager.LoadScene(currentSceneIndex); // SceneManager.LoadScene(0) : 씬의 인덱스를 통해 현재 씬 불러오기
}
}
다음 단계 로드하기
File
- Build Settings
- Add Open Scenes
통해 새로운 Scene 추가하고 Scene 순서 조정CollisionHandler.cs
편집using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionHandler : MonoBehaviour
{
void OnCollisionEnter(Collision other)
{
switch(other.gameObject.tag)
{
case "Friendly":
Debug.Log("This thing is friendly");
break;
case "Finish":
LoadNextLevel(); // Finish에 도달하면 다음 레벨로 이동
break;
case "Fuel":
Debug.Log("You picked up fuel");
break;
default:
ReloadLevel();
break;
}
}
void LoadNextLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(currentSceneIndex + 1); // 씬 인덱스 + 1 => 다음 씬으로 이동
}
void ReloadLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(currentSceneIndex);
}
}
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionHandler : MonoBehaviour
{
void OnCollisionEnter(Collision other)
{
switch(other.gameObject.tag)
{
case "Friendly":
Debug.Log("This thing is friendly");
break;
case "Finish":
LoadNextLevel();
break;
case "Fuel":
Debug.Log("You picked up fuel");
break;
default:
ReloadLevel();
break;
}
}
void LoadNextLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
if (currentSceneIndex <= 1) // to ensure we don't try to load level 2
{
int nextSceneIndex = currentSceneIndex + 1;
if (nextSceneIndex == SceneManager.sceneCountInBuildSettings) // "다음 씬 인덱스 = 우리가 가진 씬들의 총 개수"일 경우
{
nextSceneIndex = 0; // 씬 인덱스 초기화
}
SceneManager.LoadScene(nextSceneIndex);
}
}
void ReloadLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex; // buildIndex : 현재 활동하고 있는, 빌드 설정에 있는 씬의 인덱스 반환
SceneManager.LoadScene(currentSceneIndex); // SceneManager.LoadScene(0) : 씬의 인덱스를 통해 현재 씬 불러오기
}
Error존재하지 않는 scene index를 호출해서 생긴 error. index와 전체 개수를 비교하려다보니 생긴 error였다. 그래서 현재 index+1을 전체 씬 개수와 비교하는 부분을 if문을 통해 currentSceneIndex가 1보다 작거나 같은 경우에만 실행되도록 묶어주었다.
if (currentSceneIndex <= 1)
Invoke 함수를 통해 rocket이 다른 object에 부딪힌 뒤 1초 delay 추가
default:
Invoke("ReloadLevel", 1f); // 부딪힌 뒤 1초 delay
break;
StartCrashSequence
함수 사용
default:
StartCrashSequence(); // 부딪힌 뒤 1초 delay
break;
}
}
void StartCrashSequence()
{
GetComponent<Movement>().enabled = false; //rocket의 movement 컴포넌트 제어권 off | Stop player controls during the delay
Invoke("ReloadLvel", 1f); // delay setting
}
Landing Pad 도착할 경우 delay 추가 + delay second 파라미터화
[SerializeField] float levelLoadDelay = 2f;
// 생략 //
case "Finish":
StartSuccessSequence();
break;
default:
StartCrashSequence(); // 부딪힌 뒤 1초 delay
break;
}
}
void StartSuccessSequence()
{
//todo add SFX upon crash
//todo add particle effect upon crash
GetComponent<Movement>().enabled = false; //rocket의 movement 컴포넌트 제어권 off | Stop player controls during the delay
Invoke("LoadNextLevel", levelLoadDelay); // Parameterise delay setting (we can tune in the inspector)
}
void StartCrashSequence()
{
//todo add SFX upon crash
//todo add particle effect upon crash
GetComponent<Movement>().enabled = false; //rocket의 movement 컴포넌트 제어권 off | Stop player controls during the delay
Invoke("ReloadLevel", levelLoadDelay); // Parameterise delay setting (we can tune in the inspector)
}
// 생략 //
AudioSource.Play
: 재생하고 싶은 클립을 특정 지을 수 없다 AudioSource.PlayOneShot
: 파라미터를 통해 재생하고 싶은 크립을 특정 지을 수 있다.1. Audio Souce
component가 아닌 Movement(Script)
component에서 Audio 지정
// Movement.cs //
// CASH
AudioSource audioSource;
// 생략 //
void ProcessThrust()
{
if (Input.GetKey(KeyCode.Space))
{
// float force = 5f;
rb.AddRelativeForce(Vector3.up * mainThrust * Time.deltaTime);
if(!audioSource.isPlaying)
{
audioSource.PlayOneShot(mainEngine); // 파라미터 통해 재생할 오디오 클립 지정할 수 있는 메소드
}
}
2. rocket이 다른 object
, Landing Pad
와 닿았을 때 나는 효과음(crash, success) 설정
// CollisionHandler.cs//
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionHandler : MonoBehaviour
{
// PARAMETER
[SerializeField] float levelLoadDelay = 2f;
[SerializeField] AudioClip success; // success 오디오 클립 직렬화
[SerializeField] AudioClip crash; // crash 오디오 클립 직렬화
// CASH
AudioSource audioSource; // 변수 생성
void Start()
{
audioSource = GetComponent<AudioSource>(); // 캐싱
}
void OnCollisionEnter(Collision other)
{
switch(other.gameObject.tag)
{
case "Friendly":
Debug.Log("This thing is friendly");
break;
case "Finish":
StartSuccessSequence();
break;
default:
StartCrashSequence();
break;
}
}
void StartSuccessSequence()
{
audioSource.PlayOneShot(success); // success 재생
//todo add particle effect upon success
GetComponent<Movement>().enabled = false;
Invoke("LoadNextLevel", levelLoadDelay);
}
void StartCrashSequence()
{
audioSource.PlayOneShot(crash); // crash 재생
//todo add particle effect upon crash
GetComponent<Movement>().enabled = false;
Invoke("ReloadLevel", levelLoadDelay);
}
void LoadNextLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
if (currentSceneIndex <= 1)
{
int nextSceneIndex = currentSceneIndex + 1;
if (nextSceneIndex == SceneManager.sceneCountInBuildSettings)
{
nextSceneIndex = 0;
}
SceneManager.LoadScene(nextSceneIndex);
}
}
void ReloadLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(currentSceneIndex);
}
}
효과음이 연속 실행되지 않도록 설정하기
//CollisionHandler.cs//
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionHandler : MonoBehaviour
{
// PARAMETER
[SerializeField] float levelLoadDelay = 2f;
[SerializeField] AudioClip success;
[SerializeField] AudioClip crash;
// CASH
AudioSource audioSource;
//STATE
bool isTransitioning = false; // 부딪힌 경우에만 true가 된다.
void Start()
{
audioSource = GetComponent<AudioSource>();
}
void OnCollisionEnter(Collision other) // 부딪힌 다른 것이 무엇인지 물어보는 것
{
if (isTransitioning) {return;} //(isTransitioning == true)
switch(other.gameObject.tag)
{
case "Friendly":
Debug.Log("This thing is friendly");
break;
case "Finish":
StartSuccessSequence();
break;
default:
StartCrashSequence(); // 부딪힌 뒤 1초 delay
break;
}
}
void StartSuccessSequence()
{
isTransitioning = true;
audioSource.Stop(); // success 오디오 시작 전 다른 오디오 끄기
audioSource.PlayOneShot(success);
//todo add particle effect upon success
GetComponent<Movement>().enabled = false; //rocket의 movement 컴포넌트 제어권 off | Stop player controls during the delay
Invoke("LoadNextLevel", levelLoadDelay); // Parameterise delay setting (we can tune in the inspector)
}
void StartCrashSequence()
{
isTransitioning = true;
audioSource.Stop(); // crash 오디오 시작 전 다른 오디오 끄기
audioSource.PlayOneShot(crash);
//todo add particle effect upon crash
GetComponent<Movement>().enabled = false; //rocket의 movement 컴포넌트 제어권 off | Stop player controls during the delay
Invoke("ReloadLevel", levelLoadDelay);
}
void LoadNextLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
if (currentSceneIndex <= 1)
{
int nextSceneIndex = currentSceneIndex + 1;
if (nextSceneIndex == SceneManager.sceneCountInBuildSettings)
{
nextSceneIndex = 0;
SceneManager.LoadScene(nextSceneIndex);
}
}
void ReloadLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(currentSceneIndex);
}
}
※ 두 개의 씬 모두에 다 적용할 것
Particle System : 게임 객체에 추가되는 컴포넌트
Emitter : 파티클들을 방출(Emitting)하는 물체, 공간, 혹은 지점 (월드의 한 지점)
기본 Particle System 추가 : [Hierarchy] - [Effects] - [Particle System]
Particle System 파일 적용
CollisionHandler
Scripts 편집] - [Inspector 조정 메뉴 만들기] - [파일 적용]using System;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionHandler : MonoBehaviour
{
[SerializeField] float levelLoadDelay = 2f;
[SerializeField] AudioClip success;
[SerializeField] AudioClip crash;
// 추가할 두 개의 파티클 필드 생성 //
[SerializeField] ParticleSystem successParticles;
[SerializeField] ParticleSystem crashParticles;
// CollisionHandler.cs //
void StartSuccessSequence()
{
isTransitioning = true;
audioSource.Stop();
audioSource.PlayOneShot(success);
successParticles.Play(); // add //
GetComponent<Movement>().enabled = false;
Invoke("LoadNextLevel", levelLoadDelay);
}
void StartCrashSequence()
{
isTransitioning = true;
audioSource.Stop();
audioSource.PlayOneShot(crash);
crashParticles.Play(); // add //
GetComponent<Movement>().enabled = false;
Invoke("ReloadLevel", levelLoadDelay);
Looping
, Play On Awake
체크 해제 확인로켓 부스터 3가지 추가 : Rocket Jet, Right Thruster, Left Thruster
* Right Thruster
와 Left Thruster
는 Rotation Y의 부호를 달리하면 쉽게 변경 가능
Movements.cs
Play()
,Stop()
코드 추가 using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
public class Movement : MonoBehaviour
{
/* 코드 작성 순서
PARAMETERS(매개변수) - for tuning, typically set in the editor
CACHE - e.g. references for readability or speed
STATE - private instance (member) variables
*/
[SerializeField] float mainThrust = 100f;
[SerializeField] float rotationThrust = 1f;
[SerializeField] AudioClip mainEngine;
// 로켓부스터 파티클 필드 추가
[SerializeField] ParticleSystem mainEngineParticles;
[SerializeField] ParticleSystem leftThrusterParticles;
[SerializeField] ParticleSystem rightThrusterParticles;
Rigidbody rb;
AudioSource audioSource;
void Start()
{
rb = GetComponent<Rigidbody>();
audioSource = GetComponent<AudioSource>();
}
void Update()
{
ProcessThrust();
ProcessRotation();
}
void ProcessThrust()
{
if (Input.GetKey(KeyCode.Space))
{
rb.AddRelativeForce(Vector3.up * mainThrust * Time.deltaTime);
if(!audioSource.isPlaying)
{
audioSource.PlayOneShot(mainEngine);
}
// mainEngineParticles Play() 코드
if(!mainEngineParticles.isPlaying)
{
mainEngineParticles.Play();
}
}
// mainEngineParticles Stop() 코드
else
{
audioSource.Stop();
mainEngineParticles.Stop();
}
}
void ProcessRotation()
{
if (Input.GetKey(KeyCode.A))
{
ApplyRotation(rotationThrust);
// rightThrusterParticles Play() 코드
if(!rightThrusterParticles.isPlaying)
{
rightThrusterParticles.Play();
}
}
else if (Input.GetKey(KeyCode.D))
{
ApplyRotation(-rotationThrust);
// leftThrusterParticles Play() 코드
if(!leftThrusterParticles.isPlaying)
{
leftThrusterParticles.Play();
}
}
// if(A key pressed)와 else(D key pressed) 모두 실행되지 않을 경우 두 개의 ThrusterParticles 모두 중지
else
{
rightThrusterParticles.Stop();
leftThrusterParticles.Stop();
}
}
void ApplyRotation(float rotationThisFrame)
{
rb.freezeRotation = true;
transform.Rotate(Vector3.forward * rotationThisFrame * Time.deltaTime);
rb.freezeRotation = false;
}
}
Movement.cs
필드에 파일 적용[Ctrl] + [.]
- Extract method(메서드 추출)
- [F2]로 rename
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
public class Movement : MonoBehaviour
{
/* 코드 작성 순서
PARAMETERS(매개변수) - for tuning, typically set in the editor
CACHE - e.g. references for readability or speed
STATE - private instance (member) variables
*/
[SerializeField] float mainThrust = 100f;
[SerializeField] float rotationThrust = 1f;
[SerializeField] AudioClip mainEngine;
[SerializeField] ParticleSystem mainEngineParticles;
[SerializeField] ParticleSystem leftThrusterParticles;
[SerializeField] ParticleSystem rightThrusterParticles;
Rigidbody rb;
AudioSource audioSource;
void Start()
{
rb = GetComponent<Rigidbody>();
audioSource = GetComponent<AudioSource>();
}
void Update()
{
ProcessThrust();
ProcessRotation();
}
void ProcessThrust()
{
if (Input.GetKey(KeyCode.Space))
{
StartThrusting();
}
else
{
StopThrusting();
}
}
void ProcessRotation()
{
if (Input.GetKey(KeyCode.A))
{
RotateLeft();
}
else if (Input.GetKey(KeyCode.D))
{
RotateRight();
}
else
{
StopRotating();
}
}
void StartThrusting()
{
rb.AddRelativeForce(Vector3.up * mainThrust * Time.deltaTime);
if (!audioSource.isPlaying)
{
audioSource.PlayOneShot(mainEngine);
}
if (!mainEngineParticles.isPlaying)
{
mainEngineParticles.Play();
}
}
void StopThrusting()
{
audioSource.Stop();
mainEngineParticles.Stop();
}
void RotateLeft()
{
ApplyRotation(rotationThrust);
if (!rightThrusterParticles.isPlaying)
{
rightThrusterParticles.Play();
}
}
void RotateRight()
{
ApplyRotation(-rotationThrust);
if (!leftThrusterParticles.isPlaying)
{
leftThrusterParticles.Play();
}
}
void StopRotating()
{
rightThrusterParticles.Stop();
leftThrusterParticles.Stop();
}
void ApplyRotation(float rotationThisFrame)
{
rb.freezeRotation = true;
transform.Rotate(Vector3.forward * rotationThisFrame * Time.deltaTime);
rb.freezeRotation = false;
}
}
L
: 다음 레벨로 이동C
: 충돌 없애 게임 무제한 실행using System;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionHandler : MonoBehaviour
{
// PARAMETER
[SerializeField] float levelLoadDelay = 2f;
[SerializeField] AudioClip success;
[SerializeField] AudioClip crash;
[SerializeField] ParticleSystem successParticles;
[SerializeField] ParticleSystem crashParticles;
// CASH
AudioSource audioSource;
//STATE
bool isTransitioning = false;
bool collisionDisabled = false;
void Start()
{
audioSource = GetComponent<AudioSource>();
}
void Update()
{
RespondToDebugKeys();
}
void RespondToDebugKeys()
{
// L Key
if (Input.GetKeyDown(KeyCode.L))
{
LoadNextLevel();
}
// C Key
else if (Input.GetKeyDown(KeyCode.C))
{
collisionDisabled = !collisionDisabled; // toggle collision
}
}
void OnCollisionEnter(Collision other)
{
if (isTransitioning || collisionDisabled) {return;} // isTransitioning or collisionDisabled == true
switch(other.gameObject.tag)
{
case "Friendly":
Debug.Log("This thing is friendly");
break;
case "Finish":
StartSuccessSequence();
break;
default:
StartCrashSequence();
break;
}
}
void StartSuccessSequence()
{
isTransitioning = true;
audioSource.Stop();
audioSource.PlayOneShot(success);
successParticles.Play();
GetComponent<Movement>().enabled = false; /
Invoke("LoadNextLevel", levelLoadDelay); // Parameterise delay setting (we can tune in the inspector)
}
void StartCrashSequence()
{
isTransitioning = true;
audioSource.Stop();
audioSource.PlayOneShot(crash);
crashParticles.Play();
GetComponent<Movement>().enabled = false;
Invoke("ReloadLevel", levelLoadDelay);
}
void LoadNextLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
if (currentSceneIndex <= 1)
{
int nextSceneIndex = currentSceneIndex + 1;
if (nextSceneIndex == SceneManager.sceneCountInBuildSettings)
{
nextSceneIndex = 0;
}
SceneManager.LoadScene(nextSceneIndex);
}
}
void ReloadLevel()
{
int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(currentSceneIndex);
}
}
Oscillator.cs
생성using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Oscillator : MonoBehaviour
{
Vector3 startingPosition;
[SerializeField] Vector3 movementVector;
[SerializeField] [Range(0, 1)]float movementFactor;
[SerializeField] float period = 2f;
void Start()
{
startingPosition = transform.position;
Debug.Log(startingPosition);
}
void Update()
{
float cycles = Time.time / period; // 시간에 따라 계속 증가함
const float tau = Mathf.PI * 2; // 6.283의 일정한 값
float rawSinWave = Mathf.Sin(cycles * tau); // -1~1로 움직임
movementFactor = (rawSinWave + 1f) / 2f; // 0~1로 움직이도록 다시 계산
Vector3 offset = movementVector * movementFactor; // x, y, z 각 축에 movementFactor만큼 곱해주기
transform.position = startingPosition + offset;
}
}
void Update()
{
if (period == 0f) { return; } // 분모가 0이 되지 않도록
float cycles = Time.time / period; // 시간에 따라 계속 증가함
const float tau = Mathf.PI * 2; // 6.283의 일정한 값
float rawSinWave = Mathf.Sin(cycles * tau); // -1~1로 움직임
movementFactor = (rawSinWave + 1f) / 2f; // 0~1로 움직이도록 다시 계산
Vector3 offset = movementVector * movementFactor; // x, y, z 각 축에 movementFactor만큼 곱해주기
transform.position = startingPosition + offset;
}
==
는 period
와 0f
가 정말 일치할지 알 수 없다.float
은 Mathf.Epsilon
이다.Mathf.Epsilon
을 사용한다.// float의 특징으로 인해 변경된 코드 //
void Update()
{
if (period <= Mathf.Epsilon) { return; } // period에 0이 입력되어도 아무런 error가 발생하지 않음
float cycles = Time.time / period; // 시간에 따라 계속 증가함
const float tau = Mathf.PI * 2; // 6.283의 일정한 값
float rawSinWave = Mathf.Sin(cycles * tau); // -1~1로 움직임
movementFactor = (rawSinWave + 1f) / 2f; // 0~1로 움직이도록 다시 계산
Vector3 offset = movementVector * movementFactor; // x, y, z 각 축에 movementFactor만큼 곱해주기
transform.position = startingPosition + offset;
}
QuitApplication.cs
생성using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class QuitApplication : MonoBehaviour
{
void Start()
{
if(Input.GetKeyDown(KeyCode.Escape))
{
Debug.Log("we pushed escape");
Application.Quit();
}
}
void Update()
{
}
}
WebGL Build Support
다운