
ãã®ãã¥ãŒããªã¢ã«ã§ã¯ããã¬ã€ã€ãŒãã¢ã¯ã·ã§ã³ã
å·»ãæ»ãããšãã§ããã·ã³ãã«ãªã²ãŒã ãäœæããŸãã Unityã§ãããè¡ããŸãããã·ã¹ãã ãä»ã®ãšã³ãžã³ã«é©åãããããšãã§ããŸãã æåã®éšåã§ã¯ããã®é¢æ°ã®åºæ¬ãæ€èšãã2çªç®ã§ã¯ããã®ã¹ã±ã«ãã³ãèšè¿°ããããæ±çšçã«ããŸãã
ãŸãããã®ãããªã·ã¹ãã ã䜿çšããã²ãŒã ãèŠãŠã¿ãŸãããã ãã®ãã¯ããã¯ã®ããŸããŸãªã¢ããªã±ãŒã·ã§ã³ãç 究ããŠãããå·»ãæ»ãæ©èœãåããå°ããªã²ãŒã ãäœæããŸãã
äž»ãªæ©èœã®ãã¢ã³ã¹ãã¬ãŒã·ã§ã³Unityã®ææ°ããŒãžã§ã³ãšãšã³ãžã³ã®çµéšãå¿
èŠã§ãã ãœãŒã¹ã³ãŒãã¯å
¬éãããçµæãæ¯èŒã§ããŸãã
æºåã¯ããïŒ è¡ããïŒ
ãã®ã·ã¹ãã ã¯ä»ã®ã²ãŒã ã§ã©ã®ããã«äœ¿çšãããŠããŸããïŒ
ããªã³ã¹ãªããã«ã·ã£ïŒThe Sands of Timeã¯
ãã¿ã€ã ãªã¯ã€ã³ãã¡ã«ããºã ãçµ±åãããæåã®ã²ãŒã ã®1ã€ã§ããã ãã¬ã€ã€ãŒãæ»ãã ãšãã圌ã¯ã²ãŒã ãåéããã ãã§ãªãããã£ã©ã¯ã¿ãŒããŸã çããŠãããšãã«æ°ç§åã«å·»ãæ»ããããã«åè©Šè¡ããããšãã§ããŸãã
ããªã³ã¹ãªããã«ã·ã£ïŒå¿ããããç ã Sands Of Timeã® 3éšäœã§ã¯ãæéã®å·»ãæ»ããã²ãŒã ãã¬ã€ã«å®å
šã«çµ±åããŠããŸãã ããã«ããããã¬ãŒã€ãŒã¯é«éèªã¿èŸŒã¿ã®ããã«äžæãããã²ãŒã ã«æ²¡é ãããŸãŸã«ãªããŸãããã®ã¡ã«ããºã ã¯ãã²ãŒã ãã¬ã€ã ãã§ãªããã²ãŒã èªäœã®ç©èªãå®å®ã«ãçµ±åãããŠãããããããå
šäœã§èšåãããŠããŸãã
Braidã®ãããªã²ãŒã ã§ãåæ§ã®ã·ã¹ãã ã䜿çšãããŠãããã²ãŒã ãã¬ã€ãæéã®å·»ãæ»ãã«å¯æ¥ã«é¢é£ããŠããŸãã ã²ãŒã
Overwatch Tracerã®ããã€ã³ã¯ã圌女ãæ°ç§åã®å Žæã«
æ»ã ãã€ãŸããã«ããã¬ã€ã€ãŒã²ãŒã ã§ãæéã
å·»ãæ»ãèœåãæã£ãŠããŸãã äžé£ã®ã¬ãŒã·ã³ã°ã²ãŒã
GRIDã«ã¯ãã¹ãããã·ã§ããã®ä»çµã¿ããããŸããã¬ãŒã¹äžããã¬ã€ã€ãŒã¯å·»ãæ»ãã®å°ããªã¹ããã¯ãæã¡ãè»ãé倧ãªäºæ
ã«éã£ããšãã«äœ¿çšã§ããŸãã ããã«ãããã¬ãŒã¹çµäºæã®äºæ
ããçããç
©ããããããã¬ã€ã€ãŒã解æŸããŸãã
GRIDã§ã®æ·±å»ãªè¡çªã§ã¯ãäºæ
ãŸã§ã²ãŒã ãå·»ãæ»ãæ©äŒããããŸããã®ä»ã®ãŠãŒã¹ã±ãŒã¹
ãã ãããã®ã·ã¹ãã ã¯ãã¯ã€ãã¯ä¿åã®ä»£ãããšããŠã®ã¿äœ¿çšããããšã¯ã§ããŸããã å¥ã®äœ¿çšäŸã¯ãã¬ãŒã¹ã²ãŒã ããã³éåæãã«ããã¬ã€ã€ãŒã¢ãŒãã§ã®ããŽãŒã¹ããã®å®è£
ã§ãã
ãªãã¬ã€
ããã¯ãé¢æ°ã䜿çšãããã1ã€ã®èå³æ·±ãæ¹æ³ã§ãã
SUPERHOT ã
Wormsã·ãªãŒãºãããã³ã»ãšãã©ã®ã¹ããŒãã²ãŒã ã®ãããªã²ãŒã ã§äœ¿çšãããŸãã
ã¹ããŒãã®ãªãã¬ã€ã¯ããã¬ãã§è¡ãã®ãšåãããã«æ©èœããŸããã²ãŒã ãã¬ã€ã¯ãæã«ã¯ç°ãªãè§åºŠããç¹°ãè¿ã衚瀺ãããŸãã ãããè¡ãããã«ãã²ãŒã ã§ã¯ããããªã§ã¯ãªãããŠãŒã¶ãŒã®ã¢ã¯ã·ã§ã³ãèšé²ãããŸããããã«ãããããŸããŸãªè§åºŠãè§åºŠãããªãã¬ã€ãåçã§ããŸãã ã¯ãŒã ã®ã²ãŒã ã§ã¯ããªãã¬ã€ã«ãŠãŒã¢ã¢ã衚瀺ãããŸããéåžžã«é¢çœããŸãã¯å¹æçãªæ®ºå®³ã®å³æåå®è¡ã衚瀺ãããŸãã
SUPERHOTã¯åããèšé²ããŸãã ã¬ãã«ãééãããšãã²ãŒã ãã¬ã€å
šäœã®ãªãã¬ã€ã衚瀺ããããããæ°ç§ã§åãŸããŸãã
ã¹ãŒããŒããŒãããŒã€ã§é¢çœããªãã¬ã€ã ã¬ãã«ãå®äºãããšããã¬ãŒã€ãŒã¯ä»¥åã®ãã¹ãŠã®è©Šè¡ãäºãã«éãªãåã£ãŠè¡šç€ºãããŸãã
ã¹ãŒããŒããŒãããŒã€ã¬ãã«ã®çµããã«ãªãã¬ã€ããŸãã 以åã®è©Šè¡ã¯ãã¹ãŠèšé²ãããåæã«åçãããŸããã¿ã€ã ãã©ã€ã¢ã«ã®å¹œé
ãŽãŒã¹ãã¬ãŒã¹ã¯ããã¬ã€ã€ãŒã空ããŠãããã©ãã¯ãé転ããŠæé«ã®æéãèŠããããšãããã¯ããã¯ã§ãã ãããåæã«ã圌ã¯
ãŽãŒã¹ããšç«¶ããŸããããã¯ããã¬ã€ã€ãŒã®æé«ã®åã®è©Šã¿ã®ãã¹ãæ£ç¢ºã«ç¹°ãè¿ãåéæã®ãã·ã³ã§ãã ããã«çŽé¢ããããšã¯äžå¯èœã§ããã€ãŸãããã¬ãŒã€ãŒã¯æé«ã®æéãéæããããšã«éäžã§ããŸãã
äžäººã§æ
è¡ããªãããã«ããããã«ãããªãã¯èªåèªèº«ãš
競äºããããšãã§ããŸãã ãã®æ©èœã¯ã
Need for Speedã·ãªãŒãºãã
Diddy Kong RacingãŸã§ãã»ãšãã©ã®ã¬ãŒã¹ã²ãŒã ã§äœ¿çšãããŠããŸãã
Trackmania Nationsã§ã®ãŽãŒã¹ãã¬ãŒã¹ã ããã¯ãéè²ãã®é£æ床ã§ããã€ãŸãããã¬ã€ã€ãŒããŽãŒã¹ããééãããšéã¡ãã«ãç²åŸãããšããããšã§ãã è»ã®ã¢ãã«ã¯äº€å·®ããŠããããšã«æ³šæããŠãã ãããã€ãŸãããŽãŒã¹ãã¯éèŠã§ã¯ãªããééãããããšãã§ããŸãããã«ããã¬ã€ã€ãŒã¢ãŒãã®ãŽãŒã¹ã
é¢æ°ã䜿çšããå¥ã®æ¹æ³ã¯ããã«ããŠãŒã¶ãŒéåæã¢ãŒãã§ã®ãŽãŒã¹ãã§ãã ãã®ãã£ãã«äœ¿çšãããªãæ©èœã§ã¯ã1人ã®ãã¬ã€ã€ãŒã®ããŒã¿ãèšé²ããããšã«ããããã«ããã¬ã€ã€ãŒã®è©Šåãè¡ãããŸãã ããŒã¿ã¯ãŽãŒã¹ãã¬ãŒã¹ã®å Žåãšåãæ¹æ³ã§é©çšãããä»ã®ãã¬ã€ã€ãŒãšã®ç«¶äºã®ã¿ãè¡ãããŸãã
ãã®çš®ã®ç«¶äºã¯ãããŸããŸãªå°é£ã
ä¹ãåãããšãã§ãã
Trackmaniaã²ãŒã ã§äœ¿çšãããŸãã ãã®ãããªèšé²ãããã©ã€ããŒã¯ãå ±é
¬ãåãåãããã«æåããªããã°ãªããªãæµã«ãªããŸãã
æ®åœ±ã¢ã³ã¿ãŒãžã¥
äžéšã®ã²ãŒã ã§ã¯ãå·»ãæ»ãã¯åãªã楜ããããŒã«ã§ãã
Team Fortress 2ã«ã¯ãç¬èªã®ãããªãäœæã§ãããªãã¬ã€ãšãã£ã¿ãŒãçµã¿èŸŒãŸããŠããŸãã
Team Fortress 2ã®ãªãã¬ã€ãšãã£ã¿ãŒã èšé²ãããæŠéã¯ããã¬ã€ã€ãŒã®ç®ã ãã§ãªããããããèŠç¹ããèŠãããšãã§ããŸããæ©èœãæå¹ã«ãããšã以åã®äžèŽãèšé²ããã³è¡šç€ºã§ããŸãã ãã¬ã€ã€ãŒãèŠããã®ã ãã§ãªãã
ãã¹ãŠãèšé²ãããããšãéåžžã«éèŠã§ãã ããã¯ãèšé²ãããã²ãŒã ã®äžçãåãåããå
šå¡ãã©ãã«ãããã確èªããæé
ã管çã§ããããšãæå³ããŸãã
å®è£
æ¹æ³
ãã®ã·ã¹ãã ããã¹ãããã«ã¯ãç°¡åãªã²ãŒã ãå¿
èŠã§ãã äœããŸãããïŒ
ãã¬ã€ã€ãŒ
ã·ãŒã³ã«ãã¥ãŒããäœæããŸããããããã¬ã€ã€ãŒã®ãã£ã©ã¯ã¿ãŒã«ãªããŸãã 次ã«ã
Player.cs
ãšããæ°ããCïŒã¹ã¯ãªãããäœæãã
Update()
é¢æ°ã«æ¬¡ãè¿œå ããŸãã
void Update() { transform.Translate (Vector3.forward * 3.0f * Time.deltaTime * Input.GetAxis ("Vertical")); transform.Rotate (Vector3.up * 200.0f * Time.deltaTime * Input.GetAxis ("Horizontal")); }
ãããã£ãŠãç¢å°ã䜿çšããŠãã£ã©ã¯ã¿ãŒãå¶åŸ¡ã§ããŸãã ã¹ã¯ãªããããã¥ãŒãã«æ·»ä»ããŸãã Playãã¯ãªãã¯ããåŸã移åã§ããŸãã äžããç«æ¹äœãèŠãããã«ã«ã¡ã©ã®è§åºŠãå€æŽããŸãã æåŸã«ã
åºé¢ãäœæããåãããªã¢ã«ã«ç¬èªã®ãããªã¢ã«ãå²ãåœãŠãŠããã€ãå
ã移åããªãããã«ããŸãã 次ã®ãããªãã®ãåŸãããã¯ãã§ãã

WSADãšç¢å°ããŒã§ãã¥ãŒããå¶åŸ¡ããŠã¿ãŠãã ãã
ã¿ã€ã ã³ã³ãããŒã©ãŒ
次ã«ãæ°ããCïŒ
TimeController.cs
ãäœæããŠãæ°ãã空ã®
TimeController.cs
è¿œå ããŸãã 圌ã¯ã²ãŒã ã®èšé²ãšå·»ãæ»ãã管çããŸãã
ãããæ©èœããããã«ããã¬ã€ã€ãŒã®ãã£ã©ã¯ã¿ãŒã®åããèšé²ããŸãã å·»ãæ»ããã¿ã³ãã¯ãªãã¯ããåŸããã£ã©ã¯ã¿ãŒã®åº§æšãå€æŽããŸãã ãŸãããã£ã©ã¯ã¿ãŒãä¿åããå€æ°ãäœæããŸãã
public GameObject player;
çµæã®TimeControllerã¹ãããã«ãã¬ãŒã€ãŒãªããžã§ã¯ããå²ãåœãŠãŠããã¬ãŒã€ãŒãšãã®ããŒã¿ã«ã¢ã¯ã»ã¹ã§ããããã«ããŸãã

次ã«ããã¬ãŒã€ãŒããŒã¿ãä¿åããé
åãäœæããå¿
èŠããããŸãã
public ArrayList playerPositions; void Start() { playerPositions = new ArrayList(); }
次ã«ããã¬ãŒã€ãŒã®äœçœ®ãç¶ç¶çã«èšé²ããå¿
èŠããããŸãã æåŸã®ãã¬ãŒã ã«ä¿åããããã¬ãŒã€ãŒã®äœçœ®ããã¬ãŒã€ãŒã6ãã¬ãŒã æ»ã£ãäœçœ®ãããã³ãã¬ãŒã€ãŒã8ç§åïŒãŸãã¯èšå®ããé²é³æéïŒã«ãã£ãäœçœ®ããããŸãã åçããŒãæŒããšãæéã®å·»ãæ»ãæ©èœãäœæããçµæãšããŠãäœçœ®ã®é
åã«æ»ãããã¬ãŒã ããšã«ããããå²ãåœãŠãŸãã
ãŸããããŒã¿ãä¿åããŸãããïŒ
void FixedUpdate() { playerPositions.Add (player.transform.position); }
FixedUpdate()
é¢æ°ã§ã¯ãããŒã¿ãæžã蟌ã¿ãŸãã
FixedUpdate()
ã䜿çšãããã®ã¯ã1ç§ããã50ãµã€ã¯ã«ïŒãŸãã¯éžæããå€ïŒã®äžå®ã®é »åºŠã§å®è¡ãããäžå®ã®ééã§ããŒã¿ãèšé²ã§ããããã§ãã
Update()
é¢æ°ã¯ãããã»ããµãæäŸããé »åºŠã§å®è¡ããããããäœæ¥ãè€éã«ãªããŸãã
ãã®ã³ãŒãã¯ããã¬ãŒã€ãŒã®äœçœ®ããã¬ãŒã ããšã«é
åã«ä¿åããŸãã ä»ãããé©çšããå¿
èŠããããŸãïŒ
å·»ãæ»ããã¿ã³ã®ã¯ãªãã¯ãã¹ããè¿œå ããŸãã ãããè¡ãã«ã¯ãããŒã«å€æ°ãå¿
èŠã§ãã
public bool isReversing = false;
ãããŠã
Update()
é¢æ°ããã§ãã¯ã€ã³ããŸãã
void Update() { if(Input.GetKey(KeyCode.Space)) { isReversing = true; } else { isReversing = false; } }
ã²ãŒã ã
å察æ¹åã«å®è¡ãã
ã«ã¯ ãèšé²ãã代ããã«ããŒã¿ã䜿çšããå¿
èŠããããŸãã ãã¬ãŒã€ãŒã®äœçœ®ãèšé²ããã³é©çšããããã®æ°ããã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
void FixedUpdate() { if(!isReversing) { playerPositions.Add (player.transform.position); } else { player.transform.position = (Vector3) playerPositions[playerPositions.Count - 1]; playerPositions.RemoveAt(playerPositions.Count - 1); } }
ãããŠã
TimeController
ã¹ã¯ãªããå
šäœã¯
TimeController
ããã«ãªããŸãã
using UnityEngine; using System.Collections; public class TimeController: MonoBehaviour { public GameObject player; public ArrayList playerPositions; public bool isReversing = false; void Start() { playerPositions = new ArrayList(); } void Update() { if(Input.GetKey(KeyCode.Space)) { isReversing = true; } else { isReversing = false; } } void FixedUpdate() { if(!isReversing) { playerPositions.Add (player.transform.position); } else { player.transform.position = (Vector3) playerPositions[playerPositions.Count - 1]; playerPositions.RemoveAt(playerPositions.Count - 1); } } }
ãŸãã
player
ã¯ã©ã¹ã«ã
TimeController
å·»ã
TimeController
åçãããªãå Žåã«ã®ã¿ç§»åãå®è¡ãããã©ããã確èªãããã§ãã¯ãè¿œå ããŠãã ããã ããããªããšãåäœããããããªãå¯èœæ§ããããŸãã
using UnityEngine; using System.Collections; public class Player: MonoBehaviour { private TimeController timeController; void Start() { timeController = FindObjectOfType(typeof(TimeController)) as TimeController; } void Update() { if(!timeController.isReversing) { transform.Translate (Vector3.forward * 3.0f * Time.deltaTime * Input.GetAxis ("Vertical")); transform.Rotate (Vector3.up * 200.0f * Time.deltaTime * Input.GetAxis ("Horizontal")); } } }
ãããã®æ°ããè¡ã¯ãèµ·åæã«ã·ãŒã³å
ã®
TimeController
ãªããžã§ã¯ããèªåçã«æ€åºããå®è¡æã«ãã§ãã¯ããŸãã å·»ãæ»ããå®è¡ãããŠããªãå Žåã«ã®ã¿ããã£ã©ã¯ã¿ãŒãå¶åŸ¡ã§ããŸãã
ããã§ãäžçäžã移åããã¹ããŒã¹ããŒã§ãã®åããå·»ãæ»ãããšãã§ããŸãã èšäºã®æåŸã«ãããªã³ã¯ããããã±ãŒãžãããŠã³ããŒããã
TimeRewindingFunctionality01ãéããŠ
äœæ¥ã確èªã§ããŸãïŒ
ããããã¡ãã£ãšåŸ
ã£ãŠãã ãããåçŽãªãµã€ã³ããã¬ãŒã€ãŒããæåŸã«æ®ã£ãæ¹åãèŠç¶ããã®ã¯ãªãã§ããã ãªããžã§ã¯ãã®å転ãèšé²ããããšãæšæž¬ããªãã£ãããã§ãïŒ
ãããè¡ãã«ã¯ãããŒã¿ãä¿åããã³é©çšããããã«æåã«äœæãããå¥ã®é
åãå¿
èŠã§ãã
using UnityEngine; using System.Collections; public class TimeController: MonoBehaviour { public GameObject player; public ArrayList playerPositions; public ArrayList playerRotations; public bool isReversing = false; void Start() { playerPositions = new ArrayList(); playerRotations = new ArrayList(); } void Update() { if(Input.GetKey(KeyCode.Space)) { isReversing = true; } else { isReversing = false; } } void FixedUpdate() { if(!isReversing) { playerPositions.Add (player.transform.position); playerRotations.Add (player.transform.localEulerAngles); } else { player.transform.position = (Vector3) playerPositions[playerPositions.Count - 1]; playerPositions.RemoveAt(playerPositions.Count - 1); player.transform.localEulerAngles = (Vector3) playerRotations[playerRotations.Count - 1]; playerRotations.RemoveAt(playerRotations.Count - 1); } } }
å®è¡ããŠã¿ãŠãã ããïŒ
TimeRewindingFunctionality02ã¯æ¡åŒµããŒãžã§ã³ã§ãã ããã§ããã¥ãŒããã¬ãŒã€ãŒã¯æéãããã®ãŒãããšãã§ãã察å¿ããç¬éã«èŠããšããã«è¡šç€ºãããŸãã
ãããã«
å®å
šã«åäœããæéå·»ãæ»ãã·ã¹ãã ãåããã²ãŒã ã®ç°¡åãªãããã¿ã€ããäœæããŸãããããŸã å®å
šãšã¯ã»ã©é ãç¶æ
ã§ãã ããã«ãã¯ããã«å®å®ããæ®éçãªãã®ã«ããèå³æ·±ãå¹æãè¿œå ããŸãã
ãŸã ãããªããã°ãªããªãããšã¯æ¬¡ã®ãšããã§ãã
- 12çªç®ã®ãã¬ãŒã ããšã«ã®ã¿èšé²ããèšé²ããããã¬ãŒã éã§ç¶æ
ãè£éããŠãããŒã¿éã倧ãããªããããªãããã«ããŸã
- é
åã倧ãããªãããããã²ãŒã ãã¯ã©ãã·ã¥ããªãããã«ããã¬ãŒã€ãŒã®æåŸã®75ã®äœçœ®ãšã¿ãŒã³ã®ã¿ãèšé²ããŸãã
ããã«ããã¬ã€ã€ãŒã ãã§ãªããã®ã·ã¹ãã ãæ©èœããããã«ãã®ã·ã¹ãã ãæ¡åŒµããæ¹æ³ã«ã€ããŠãèããŸãã
- 1人ã®ãã¬ãŒã€ãŒã ãã§ãªãèšé²ããæ¹æ³
- å·»ãæ»ãå¹æãè¿œå ããŸãïŒVHSä¿¡å·ã®ãŒãããªã©ïŒ
- ç¬èªã®ã¯ã©ã¹ã䜿çšããŠãé
åã§ã¯ãªããã¬ãŒã€ãŒã®äœçœ®ãšå転ãä¿åããŸã
Unityãããžã§ã¯ãã¢ãŒã«ã€ã
ããã§ãæéãåã®ãã€ã³ãã«å·»ãæ»ãããšãã§ããã·ã³ãã«ãªã²ãŒã ãäœæããŸããã ããã§ããã®æ©èœãæ¹åãããã®äœ¿çšãããã«é¢çœãããããšãã§ããŸãã
ããå°ãªãããŒã¿ãæžã蟌ã¿ãè£éãã
çŸæç¹ã§ã¯ããã¬ãŒã€ãŒã®äœçœ®ãèšé²ãã1ç§éã«
50åã¿ãŒã³ããŸãã ãã®ãããªå€§éã®ããŒã¿ã¯ããã«èããããªããªããç¹ã«è€éãªã²ãŒã ã匱ãã¢ãã€ã«ããã€ã¹ã§é¡èã«ãªããŸãã
代ããã«ã1ç§éã«4åããèšé²ã§ããããããã®ããŒãã¬ãŒã éã®äœçœ®ãšå転ãè£éã§ããŸãã ãããã£ãŠãçç£æ§ã®92ïŒ
ãç¯çŽã§ããŸãããŸããçµæã¯äžç¬ã§åçŸããããããæ¯ç§50ãã¬ãŒã ã®èšé²ãšåºå¥ã§ããŸããã
xãã¬ãŒã ããšã«ããŒãã¬ãŒã ãèšé²ããããšããå§ããŸãã ãããè¡ãã«ã¯ãæåã«æ°ããå€æ°ãå¿
èŠã§ãã
public int keyframe = 5; private int frameCounter = 0;
keyframe
å€æ°ã¯ããã¬ã€ã€ãŒããŒã¿ãæžã蟌ã
FixedUpdate
ã¡ãœããã®
keyframe
ã§ãã çŸæç¹ã§ã¯ãå€
5ãå²ãåœãŠãããŠããŸãã
FixedUpdate
ã
FixedUpdate
ã¡ãœããã®5ãµã€ã¯ã«ããšã«ããŒã¿ãèšé²ãããŸãã
FixedUpdate
ã¯æ¯ç§50åå®è¡ããããããæ¯ç§10ãã¬ãŒã ãèšé²ãããŸãã
frameCounter
å€æ°ã¯ã次ã®ããŒãã¬ãŒã ãŸã§ãã¬ãŒã ã«ãŠã³ã¿ãŒãšããŠäœ¿çšãããŸãã
次ã«ã
FixedUpdate
é¢æ°ã®èšé²ãããã¯ã次ã®ããã«å€æŽããŸãã
if(!isReversing) { if(frameCounter < keyframe) { frameCounter += 1; } else { frameCounter = 0; playerPositions.Add (player.transform.position); playerRotations.Add (player.transform.localEulerAngles); } }
ä»ããã²ãŒã ãéå§ããããšãããšãä»ããå·»ãæ»ãã«ãããæéã倧å¹
ã«ççž®ãããããšãããããŸãã èšé²ããããŒã¿ãå°ãªãããéåžžã®é床ã§åçããããã«çºçããŸããã ä¿®æ£ããå¿
èŠããããŸãã
ãŸããããŒã¿ãæžã蟌ãŸãã«åçãã
frameCounter
ãå¥ã®
frameCounter
å€æ°ãå¿
èŠã§ãã
private int reverseCounter = 0;
ããŒã¿ãæžã蟌ãã®ãšåãæ¹æ³ã§äœ¿çšããããã«ããã¬ãŒã€ãŒã®äœçœ®ã埩å
ããã³ãŒããä¿®æ£ããŸãã
FixedUpdate
é¢æ°ã¯æ¬¡ã®ããã«ãªããŸãã
void FixedUpdate() { if(!isReversing) { if(frameCounter < keyframe) { frameCounter += 1; } else { frameCounter = 0; playerPositions.Add (player.transform.position); playerRotations.Add (player.transform.localEulerAngles); } } else { if(reverseCounter > 0) { reverseCounter -= 1; } else { player.transform.position = (Vector3) playerPositions[playerPositions.Count - 1]; playerPositions.RemoveAt(playerPositions.Count - 1); player.transform.localEulerAngles = (Vector3) playerRotations[playerRotations.Count - 1]; playerRotations.RemoveAt(playerRotations.Count - 1); reverseCounter = keyframe; } } }
ä»ãæéãå·»ãæ»ããšãããã¬ãŒã€ãŒã¯ãªã¢ã«ã¿ã€ã ã§åã®äœçœ®ã«ãžã£ã³ãããŸãïŒ
ããããç§ãã¡ã¯ããããŸã£ããæã¿ãŸããã§ããã ãããã®ããŒãã¬ãŒã éã®äœçœ®ãè£éããå¿
èŠããããŸãããããã¯ããå°ãè€éã«ãªããŸãã ãŸãã4ã€ã®å€æ°ãå¿
èŠã§ãã
private Vector3 currentPosition; private Vector3 previousPosition; private Vector3 currentRotation; private Vector3 previousRotation;
ãããã¯ãçŸåšã®ããŒã¿ãŸã§ãçŸåšã®ãã¬ãŒã€ãŒããŒã¿ãš1ã€ã®èšé²ãããããŒãã¬ãŒã ãä¿åããã®ã§ããããã®éãè£éã§ããŸãã
次ã«ããã®é¢æ°ãå¿
èŠã§ãã
void RestorePositions() { int lastIndex = keyframes.Count - 1; int secondToLastIndex = keyframes.Count - 2; if(secondToLastIndex >= 0) { currentPosition = (Vector3) playerPositions[lastIndex]; previousPosition = (Vector3) playerPositions[secondToLastIndex]; playerPositions.RemoveAt(lastIndex); currentRotation = (Vector3) playerRotations[lastIndex]; previousRotation = (Vector3) playerRotations[secondToLastIndex]; playerRotations.RemoveAt(lastIndex); } }
è£éãå®è¡ããäœçœ®å€æ°ãšå転å€æ°ã«é¢é£æ
å ±ãå²ãåœãŠãŸãã 2ã€ã®ç°ãªããã€ã³ãã«å¯ŸããŠåŒã³åºããããå¥ã®é¢æ°ã§ãããè¡ããŸãã
ããŒã¿å埩ãããã¯ã¯æ¬¡ã®ããã«ãªããŸãã
if(reverseCounter > 0) { reverseCounter -= 1; } else { reverseCounter = keyframe; RestorePositions(); } if(firstRun) { firstRun = false; RestorePositions(); } float interpolation = (float) reverseCounter / (float) keyframe; player.transform.position = Vector3.Lerp(previousPosition, currentPosition, interpolation); player.transform.localEulerAngles = Vector3.Lerp(previousRotation, currentRotation, interpolation);
é¢æ°ãåŒã³åºããŠãããŒãã¬ãŒã ã®ç¹å®ã®ééã§é
åããæåŸããæåŸãã2çªç®ã®ããŒã¿ã»ãããååŸããŸãïŒãã®å Žåãããã¯
5ã§ã ïŒãã埩å
ãå®è¡ãããæåã®ãµã€ã¯ã«ã§ãåŒã³åºãå¿
èŠããããŸãã ãããã£ãŠã次ã®ãããã¯ãå¿
èŠã§ãã
if(firstRun) { firstRun = false; RestorePositions(); }
åäœãããã«ã¯ã
firstRun
å€æ°ãå¿
èŠã§ãã
private bool firstRun = true;
ã¹ããŒã¹ããŒãæŸãããšãã«ãªã»ããããã«ã¯ïŒ
if(Input.GetKey(KeyCode.Space)) { isReversing = true; } else { isReversing = false; firstRun = true; }
è£éã®ä»çµã¿ã¯æ¬¡ã®ãšããã§ããæåŸã«ä¿åãããããŒãã¬ãŒã ã䜿çšãã代ããã«ããã®ã·ã¹ãã ã¯æåŸã®æåŸãã2çªç®ã®ãã¬ãŒã ãåãåãããããã®éã§ããŒã¿ãè£éããŸãã è£éã®éã¯ããã¬ãŒã éã®çŸåšã®è·é¢ã«äŸåããŸãã
è£éã¯ãçŸåšããã³ä»¥åã®äœçœ®ïŒãŸãã¯å転ïŒãæž¡ãLerpé¢æ°ã«ãã£ãŠå®è¡ãããŸãã 次ã«ãè£éä¿æ°ãèšç®ãããŸããè£éä¿æ°ã®å€ã¯
0ã1ã§ãã 次ã«ããã¬ãŒã€ãŒã¯ãä¿åããã2ã€ã®ãã€ã³ãã®éã«é
眮ãããŸããããšãã°ãæåŸã®ããŒãã¬ãŒã ãžã®éäžã§40ïŒ
ã«ãªããŸãã
åããé
ãããŠãã¬ãŒã ããšã«åçãããšããããã®ããŒãã¬ãŒã éã§ãã£ã©ã¯ã¿ãŒãã©ã®ããã«ç§»åããããå®éã«èŠãããšãã§ããŸãããåçã®éçšã§ã¯æç¥ã§ããŸããã
ãããã£ãŠãã¿ã€ã ãªã¯ã€ã³ãã¹ããŒã ã®è€éãã倧å¹
ã«åæžããããå®å®ãããŸããã
åºå®æ°ã®ãã¬ãŒã ã®ã¿ãèšé²ãã
ä¿åã§ãããã¬ãŒã ã®æ°ã倧å¹
ã«æžããããšã«ãããã·ã¹ãã ã倧éã®ããŒã¿ãä¿åããªãããã«ããããšãã§ããŸãã
çŸåšã¯ãã¢ã¬ã€ã«æžã蟌ãŸãã倧éã®ããŒã¿ã§ãããé·æé䜿çšããããã«ã¯èšèšãããŠããŸããã ã¢ã¬ã€ã倧ãããªããšãé¢åã«ãªããã¢ã¯ã»ã¹ã«æéãããããã·ã¹ãã å
šäœãäžå®å®ã«ãªããŸãã
ãããä¿®æ£ããããã«ãé
åãç¹å®ã®ãµã€ãºãã倧ãããªã£ããã©ããã確èªããã³ãŒããè¿œå ã§ããŸãã ä¿åãã1ç§ãããã®ãã¬ãŒã æ°ãããã£ãŠããå Žåãã²ãŒã ã«å¹²æžãããè€éããå¢ããªãããã«ãä¿åã«å¿
èŠãªå·»ãæ»ãæéã決å®ã§ããŸãã ããªãè€éãª
ããªã³ã¹ãªããã«ã·ã£ã§ã¯ãå·»ãæ»ãæéã¯çŽ15ç§ã«å¶éãããŠãããããæè¡çã«åçŽãª
ãã¬ãŒãã²ãŒã ã§ã¯ãå·»ãæ»ãã¯ç¡éã«ãªããŸãã
if(playerPositions.Count > 128) { playerPositions.RemoveAt(0); playerRotations.RemoveAt(0); }
é
åãç¹å®ã®ãµã€ãºãè¶
ãããšãæåã®èŠçŽ ãåé€ããŸãã ãã®ããããã¬ãŒã€ãŒãå·»ãæ»ãããšãã§ããããŒã¿ãåžžã«ä¿åããå¹çã劚ããããšã¯ãããŸããã èšé²ããã³åçã³ãŒãã®åŸã«ââããã®ã³ãŒãã
FixedUpdate
é¢æ°ã«æ¿å
¥ããŸãã
ç¬èªã®ã¯ã©ã¹ã䜿çšããŠãã¬ãŒã€ãŒããŒã¿ãä¿åãã
ãã¬ãŒã€ãŒã®äœçœ®ãšå転ã2ã€ã®å¥ã
ã®é
åã«èšé²ããŸãã ããã¯æ©èœããŸããã2ã€ã®å Žæããåæã«ããŒã¿ãèªã¿æžãããããšãåžžã«èŠããŠããå¿
èŠããããŸãã ãã ããããããã¹ãŠã®ããŒã¿ãæ ŒçŽããããã®ã¯ã©ã¹ãšãå°æ¥çã«ã¯ä»ã®ã¯ã©ã¹ïŒãããžã§ã¯ãã«å¿
èŠãªå ŽåïŒãåå¥ã«äœæããããšãã§ããŸãã
ããŒã¿ã®ã³ã³ãããšããŠäœ¿çšããããã€ãã£ãã¯ã©ã¹ã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
public class Keyframe { public Vector3 position; public Vector3 rotation; public Keyframe(Vector3 position, Vector3 rotation) { this.position = position; this.rotation = rotation; } }
ã¯ã©ã¹ã®å®£èšãéå§ããåã«ãTimeController.csãã¡ã€ã«ã«è¿œå ã§ããŸãã 圌ã¯ããã¬ã€ã€ãŒã®äœçœ®ãšå転ãç¶æããã³ã³ãããäœæããŸãã ãã¶ã€ãã䜿çšãããšãå¿
èŠãªãã¹ãŠã®æ
å ±ã䜿çšããŠçŽæ¥äœæã§ããŸãã
ã¢ã«ãŽãªãºã ã®æ®ãã®éšåã¯ãæ°ããã·ã¹ãã ã§åäœããããã«é©åãããå¿
èŠããããŸãã Startã¡ãœããã§ãé
åãåæåããå¿
èŠããããŸãã
keyframes = new ArrayList();
ãããŠä»£ããã«ïŒ
playerPositions.Add (player.transform.position); playerRotations.Add (player.transform.localEulerAngles);
Keyframeãªããžã§ã¯ãã«çŽæ¥ä¿åã§ããŸãã
keyframes.Add(new Keyframe(player.transform.position, player.transform.localEulerAngles));
ããã§ã¯ããã¬ãŒã€ãŒã®äœçœ®ãšå転ã1ã€ã®ãªããžã§ã¯ãã«è¿œå ãããããåäžã®é
åã«è¿œå ããŸããããã«ãããã¢ã«ãŽãªãºã ã®è€éãã倧å¹
ã«è»œæžãããŸãã
ãŒããå¹æãè¿œå ããŠãå·»ãæ»ããæå¹ã§ããããšã瀺ããŸã
æéãå·»ãæ»ãããŠããããšãå ±åããäœããã®ãµã€ã³ãæ¬åœã«å¿
èŠã§ãã ãããŸã§
ç§ãã¡ã ãããã
ã«ã€ããŠç¥ã£ãŠããŠããã®ãããªæ¯ãèãã¯ãã¬ã€ã€ãŒã«ãšã£ãŠæ··ä¹±ãããå¯èœæ§ããããŸãã ãã®ãããªç¶æ³ã§ã¯ãèŠèŠçãªïŒç»é¢ã®ããããªãŒãããªã©ïŒãšãµãŠã³ãïŒã¹ããŒããŠã³ããŠé³æ¥œãéé ã§åçããïŒã®äž¡æ¹ã«ã€ããŠãå®è¡äžã®å·»ãæ»ãã«ã€ããŠãã¬ãŒã€ãŒã«éç¥ããããŸããŸãªä¿¡å·ãè¿œå ãããšäŸ¿å©ã§ãã
å°ããŒãããè¿œå ããŠã
ããªã³ã¹ãªããã«ã·ã£ã¹ã¿ã€ã«
ã§äœããããŸãããã
ããªã³ã¹ãªããã«ã·ã£ã§ã®å·»ãæ»ãæéïŒå¿ããããç Unityã§ã¯ãè€æ°ã®ã«ã¡ã©ãšãã§ã¯ããéããããšãã§ããŸããå®éšããããšã§ããããžã§ã¯ãã«æé©ãªã«ã¡ã©ãšãã§ã¯ããéžæã§ããŸãã
åºæ¬çãªå¹æã䜿çšããã«ã¯ããŸãããããã€ã³ããŒãããå¿
èŠããããŸãã ãããè¡ãã«ã¯ã
Assets> Import Package> Effectsã«ç§»åã ãæäŸãããŠãããã®ããã¹ãŠã€ã³ããŒãããŸãã

èŠèŠå¹æã¯ã«ã¡ã©ã«çŽæ¥é©çšã§ããŸãã
[ã³ã³ããŒãã³ã]> [ç»åå¹æ]ã«ç§»åãã
ãŒãããš
ãã«ãŒã å¹æãè¿œå ããŸãã ãããã®çµã¿åããã¯ãç§ãã¡ãç®æããŠããè¯ãå¹æãçã¿åºããŸãã

ãããã¯åºæ¬èšå®ã§ãã ãããžã§ã¯ãã«å¿ããŠã«ã¹ã¿ãã€ãºã§ããŸãã
ä»ããã²ãŒã ãéå§ããããšãããšãåžžã«ãšãã§ã¯ãã䜿çšãããŸãã

次ã«ãæå¹åããã³ç¡å¹åããæ¹æ³ãåŠç¿ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ã
TimeController
ãšãã§ã¯ãã
TimeController
ã€ã³ããŒãã
TimeController
ã ããããæåã«è¿œå ããŸãã
using UnityStandardAssets.ImageEffects;
TimeController
ããã«ã¡ã©ã«ã¢ã¯ã»ã¹ããã«ã¯ã次ã®å€æ°ãè¿œå ããŸãã
private Camera camera;
ãããŠã
Start
é¢æ°ã§å€ãå²ãåœãŠãŸãã
camera = Camera.main;
次ã«ã次ã®ã³ãŒããè¿œå ããŠãæéãå·»ãæ»ããšãã«å¹æãæå¹ã«ããŸãã
void Update() { if(Input.GetKey(KeyCode.Space)) { isReversing = true; camera.GetComponent<Blur>().enabled = true; camera.GetComponent<Bloom>().enabled = true; } else { isReversing = false; firstRun = true; camera.GetComponent<Blur>().enabled = false; camera.GetComponent<Bloom>().enabled = false; } }
ã¹ããŒã¹ããŒãæŒããšãã·ãŒã³ã®æéãå·»ãæ»ãã ãã§ãªããã«ã¡ã©ãå·»ãæ»ãå¹æãæå¹ã«ããŠãäœãèµ·ãã£ãŠãããããã¬ãŒã€ãŒã«éç¥ããŸãã
ãã¹ãŠã®
TimeController
ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
using UnityEngine; using System.Collections; using UnityStandardAssets.ImageEffects; public class Keyframe { public Vector3 position; public Vector3 rotation; public Keyframe(Vector3 position, Vector3 rotation) { this.position = position; this.rotation = rotation; } } public class TimeController: MonoBehaviour { public GameObject player; public ArrayList keyframes; public bool isReversing = false; public int keyframe = 5; private int frameCounter = 0; private int reverseCounter = 0; private Vector3 currentPosition; private Vector3 previousPosition; private Vector3 currentRotation; private Vector3 previousRotation; private Camera camera; private bool firstRun = true; void Start() { keyframes = new ArrayList(); camera = Camera.main; } void Update() { if(Input.GetKey(KeyCode.Space)) { isReversing = true; camera.GetComponent<Blur>().enabled = true; camera.GetComponent<Bloom>().enabled = true; } else { isReversing = false; firstRun = true; camera.GetComponent<Blur>().enabled = false; camera.GetComponent<Bloom>().enabled = false; } } void FixedUpdate() { if(!isReversing) { if(frameCounter < keyframe) { frameCounter += 1; } else { frameCounter = 0; keyframes.Add(new Keyframe(player.transform.position, player.transform.localEulerAngles)); } } else { if(reverseCounter > 0) { reverseCounter -= 1; } else { reverseCounter = keyframe; RestorePositions(); } if(firstRun) { firstRun = false; RestorePositions(); } float interpolation = (float) reverseCounter / (float) keyframe; player.transform.position = Vector3.Lerp(previousPosition, currentPosition, interpolation); player.transform.localEulerAngles = Vector3.Lerp(previousRotation, currentRotation, interpolation); } if(keyframes.Count > 128) { keyframes.RemoveAt(0); } } void RestorePositions() { int lastIndex = keyframes.Count - 1; int secondToLastIndex = keyframes.Count - 2; if(secondToLastIndex >= 0) { currentPosition = (keyframes[lastIndex] as Keyframe).position; previousPosition = (keyframes[secondToLastIndex] as Keyframe).position; currentRotation = (keyframes[lastIndex] as Keyframe).rotation; previousRotation = (keyframes[secondToLastIndex] as Keyframe).rotation; keyframes.RemoveAt(lastIndex); } } }
ãããžã§ã¯ãããã±ãŒãžãããŠã³ããŒãã
㊠ãè©ŠããŠã¿ãŠãã ããã
ãŸãšãããš
ã¿ã€ã ãªã¯ã€ã³ãã²ãŒã ã倧å¹
ã«æ¹åãããŸããã ã¢ã«ãŽãªãºã ã¯å€§å¹
ã«æ¹åãããæ¶è²»é»åã¯90ïŒ
åæžãããå®å®ããŠããŸãã æéãå·»ãæ»ãããŠããããšããã¬ã€ã€ãŒã«ç¥ãããèå³æ·±ãå¹æãè¿œå ããŸããã
ããã«åºã¥ããŠå®éã®ã²ãŒã ãäœæããæãæ¥ãŸããïŒ