You are on page 1of 31

Observasi Alam Semesta

Source Code, Background, How-it-Works Process


Tentang Observasi Alam Semesta

Tentang Aplikasi
Observasi Alam Semesta adalah Aplikasi Media Pembelajaran yang
mengangkat Topik Astronomi sebagai materi utama. Astronomi adalah studi
tentang Angkasa Luar. Astronomi pada masa ini sangat berkembang dinamis
seiring majunya teknologi di era modern ini.

Tentang Engine – Unity


Media Pembelajaran ini dibuat berdasarkan Platform Unity, yaitu
Platform 3D dan 2D yang sebagian besar digunakan oleh Produsen
Game Berkualitas. Unity Menggunakan Mono Scripting Engine berbasis
C# dan JS, sehingga dapat mengekpor hingga 22 Platform yang
berbeda. Workflow Unity sangat terkustomisasi sehingga dapat
digunakan diberbagai bidang dan keperluan.

Tentang Materi – Wikipedia


99% Materi bersumber pada Wikipedia. Wikipedia adalah Ensiklopedia
yang Multibahasa, Berbasis Web, Gratis, dan dapat diakses oleh seluruh
pengguna Internet. Wikipedia (Versi English) memiliki lebih dari 37 Juta
Artikel yang semuanya ditulis oleh para Volunteers tanpa dibayar. Lebih
dari Puluhan Ribu artikel dalam kondisi baik, yang tentunya mempunyai
informasi dan rujukan yang lebih kaya dan lengkap.

Tentang Media – NASA


Ratusan Media Gambar dimuat di dalam Media Pembelajaran
ini. Sebagian besar penampakan benda langit terambil dari Foto
dari Website NASA. NASA adalah Organisasi Pemerintah AS yang
berwenang untuk Menjalankan Program Angkasa, Penelitian
Benda Angkasa, dan Aeronautik. Gambar-Gambar yang dimuat
di websitenya (kecuali untuk logo NASA sendiri) berlisensi atas
Public Domain, sehingga dapat dimuat diberbagai media massa
dan program edukasi lain.

1
Pemuatan Data – Tata Surya
Hal pertama yang dilakukuan ialah memuat data kememori, dan mengolahnya hingga tampil
kelayar.

Memuat XML Data – Statistik Planet


void Awake() //Respon saat Startup Awal
{
stat.LoadXML();
ToMode0(); //Memacu Load Data Lainnya, Lihat Sistem Penggantian Mode
}
public void LoadXML()
{
doc = new XmlDocument();
doc.LoadXml(data.text); //Load SolarInfoStat.xml
if (panelExist == null)
panelExist = new bool[5];
for (int i = 0; i < orbiter.Length; i++)
{
string id = "/planets/" + orbiter[i].id;
orbiter[i].Par = new float[]{
float.Parse(doc.SelectSingleNode ( id + "/orbit/@perihelion").Value) *
(Mathf.Pow(10, float.Parse(doc.SelectSingleNode ( id +
"/orbit/@mult").Value)-8)),
float.Parse(doc.SelectSingleNode ( id + "/orbit/@tilt").Value),
float.Parse(doc.SelectSingleNode ( id + "/orbit/@rotation").Value) * 24,
float.Parse(doc.SelectSingleNode ( id + "/orbit/@periode").Value) *
8760,
float.Parse(doc.SelectSingleNode ( id + "/orbit/@inclination").Value),
float.Parse(doc.SelectSingleNode ( id + "/orbit/@eccentricity").Value),
float.Parse(doc.SelectSingleNode ( id + "/orbit/@long_ascend").Value),
float.Parse(doc.SelectSingleNode ( id + "/physics/@radius").Value) /
200000
}; //Masukkan Data kesetiap Planet, Lihat Mekanika Orbit Planet
orbiter[i].mesh.localScale = Vector3.one * (float.Parse(doc.SelectSingleNode
( id + "/physics/@radius").Value) / 200000);
}}

Memuat Window Statistik


public void Load(string planetId, SolarPlanetCracker crac){ //Mode 2 Diaktifkan
if(doc==null)
LoadXML ();
soc=crac;
if(planetId=="sun")
soc=sunCrack;
planetId = "/planets/" + planetId;
XmlNode p = doc.SelectSingleNode(planetId);
//Lihat-lihat apakah data tersebut ada, jika tidak, jangan tampilkan
panelExist[0] = p["physics"] != null;
panelExist[1] = p["orbit"] != null;
panelExist[2] = p["core"] != null;
panelExist[3] = p["surface"] != null;
panelExist[4] = p["satellite"] != null;
panelTxt[0].text = p.Attributes["name"].Value;
panelTxt[1].text = p.Attributes["type"].Value;
panelTxt[2].text = p.Attributes["family"].Value;

if(panelExist[0]){ //Panel 1, Fisik


physicTxt[0].text = cStr( doc.SelectSingleNode ( planetId +
"/physics/@radius").Value) + " km";
physicTxt[1].text = cStr( doc.SelectSingleNode ( planetId + "/physics/@mass").Value
,doc.SelectSingleNode (planetId + "/physics/@mass_").Value) + " kg";

2
physicTxt[2].text = cStr( doc.SelectSingleNode ( planetId +
"/physics/@surface").Value
,doc.SelectSingleNode (planetId + "/physics/@surface_").Value) + " km²";
physicTxt[3].text = cStr( doc.SelectSingleNode ( planetId + "/physics/@volume").Value
,doc.SelectSingleNode (planetId + "/physics/@volume_").Value) + " km³";
physicTxt[4].text = cStr( doc.SelectSingleNode ( planetId +
"/physics/@density").Value) + " g/cm³";
physicTxt[5].text = cStr( doc.SelectSingleNode ( planetId +
"/physics/@gravity").Value) + " m/s²";
physicTxt[6].text = cStr( doc.SelectSingleNode ( planetId +
"/physics/@escape").Value) + " m/s";
physicTxt[7].text = cStr( doc.SelectSingleNode ( planetId + "/physics/@temp").Value)
+ " K";
}
if(panelExist[1]){ //Panel 2, Orbit
orbitTxt[0].text = cStr( doc.SelectSingleNode ( planetId + "/orbit/@rotation").Value)
+ " Hari";
orbitTxt[1].text = cStr( doc.SelectSingleNode ( planetId + "/orbit/@periode").Value)
+ " Tahun";
orbitTxt[2].text = cStr( doc.SelectSingleNode ( planetId + "/orbit/@speed").Value) +
" km/s";
orbitTxt[3].text = cStr( doc.SelectSingleNode ( planetId + "/orbit/@average").Value
,doc.SelectSingleNode (planetId + "/orbit/@mult").Value) + " km";
orbitTxt[4].text = cStr( doc.SelectSingleNode ( planetId + "/orbit/@aphelion").Value
,doc.SelectSingleNode (planetId + "/orbit/@mult").Value) + " km";
orbitTxt[5].text = cStr( doc.SelectSingleNode ( planetId +
"/orbit/@perihelion").Value
,doc.SelectSingleNode (planetId + "/orbit/@mult").Value) + " km";
orbitTxt[6].text = cStr( doc.SelectSingleNode ( planetId + "/orbit/@tilt").Value) +
"⁰";
orbitTxt[7].text = cStr( doc.SelectSingleNode ( planetId +
"/orbit/@inclination").Value) + "⁰";
orbitTxt[8].text = cStr( doc.SelectSingleNode ( planetId +
"/orbit/@eccentricity").Value);
}
if(panelExist[2]){ //Panel 3, Inti
XmlNodeList x = doc.SelectSingleNode ( planetId + "/core").ChildNodes;
coreImage.texture = coreReference[int.Parse( doc.SelectSingleNode(planetId +
"/core/@id").Value)];
for (int i = 0; i < 5; i++) {
if(i < x.Count){
coreColor[i].color = HexToRGB(x[i].Attributes["color"].Value);
coreLabel[i].text = x[i].Attributes["name"].Value;
coreValue[i].text = x[i].Attributes["value"].Value + "%";
}else{
coreColor[i].color = clrTransparent;
coreLabel[i].text = String.Empty;
coreValue[i].text = String.Empty;
}
}
}
if(panelExist[3]){ //Panel 4, Atmosfir
XmlNodeList x = doc.SelectSingleNode ( planetId + "/surface").ChildNodes;
surfaceImage.texture = surfaceReference[int.Parse(
doc.SelectSingleNode(planetId + "/surface/@id").Value)];
for (int i = 0; i < 5; i++) {
if(i < x.Count){
surfaceColor[i].color = HexToRGB(x[i].Attributes["color"].Value);
surfaceLabel[i].text = x[i].Attributes["name"].Value;
surfaceValue[i].text = x[i].Attributes["value"].Value + "%";
}else{
surfaceColor[i].color = clrTransparent;
surfaceLabel[i].text = String.Empty;
surfaceValue[i].text = String.Empty;
}}}

if(panelExist[4]){ //Panel 5, Satelit


moonNode = doc.SelectSingleNode ( planetId + "/satellite").ChildNodes;
moonCur = 0;
3
XmlNode cur = moonNode[0];
if( cur.Name == "s"){
moonLabel[0].text = cur.Attributes["name"].Value;
moonLabel[1].text = cStr( cur.Attributes["diameter"].Value) + " Km";
moonLabel[2].text = cStr( cur.Attributes["mass"].Value) + " Km";
moonLabel[3].text = cStr( cur.Attributes["average"].Value) + " Km";
moonLabel[4].text = cStr( cur.Attributes["periode"].Value) + " Hari";
moonImage.sprite = moonReference[int.Parse(cur.Attributes["id"].Value)];
moonO.gameObject.SetActive(false);
moonS.gameObject.SetActive(true);
moonS.localScale = Vector3.one;
}else{
moonLabel[0].text = cur.Attributes["count"].Value + " Satelit";
moonLabel[5].text = cur.InnerText.Replace('|','\n');
moonO.gameObject.SetActive(true);
moonS.gameObject.SetActive(false);
moonO.localScale = Vector3.one;
}}
panelCur=0;
panelLabel.text = panelStr[0];
panels[0].gameObject.SetActive(true);
panels[0].localScale = Vector3.one;
panels[1].gameObject.SetActive(false);
panels[2].gameObject.SetActive(false);
panels[3].gameObject.SetActive(false);
panels[4].gameObject.SetActive(false);
}

const string supers="⁰¹²³⁴⁵⁶⁷⁸⁹";


static string cStr(string v){
float w = float.Parse (v,CultureInfo.InvariantCulture.NumberFormat);
if (w == (float)((int)w))
return w.ToString("#,#0");
else
return w.ToString("#,#0.00");
}
static string cStr(string v, string e){
string ss=" x 10";
for (int i = 0; i < e.Length; i++) {
ss+= supers[(int)char.GetNumericValue(e[i])];
}
return cStr (v) + ss;
}

Memuat Window Detail


public void Load(string planetId){ //Mode 3 Diaktifkan
if(doc==null)
Start ();
planetId = "/planets/" + planetId;
XmlNode p = doc.SelectSingleNode(planetId);
curNode = p.ChildNodes;
curIdx = 0;
transform.localScale=Vector3.one;
title.text = curNode[0].Attributes["title"].Value;
com.text = curNode[0].Attributes["caption"].Value;
detail.text = curNode[0].InnerText;
image.sprite = images[int.Parse(curNode[0].Attributes["id"].Value)];
}
void Start () {
doc = new XmlDocument();
doc.LoadXml (data.text); //Muat SolarInfoDetail.xml
}

4
Sistem Navigasi UI – Tata Surya
Dalam Scene Tata Surya, terbagi menjadi 4 Mode, yaitu saat menjelajahi orbit Planet, Memilih
Planet, Window Statistik, dan Window Detail.

Sistem Penggantian Mode


int mode = 0; //0 = Orbit Slots; 1 = Planet Lookup; 2 = Statistics; 3 =
Detail
public void ToMode0() //Default Mode
{
mode = 0;
slots [curSlot].Fade(true);
slots [curSlot].Return();
curRot.x = Mathf.Repeat(curRot.x,360);
transform.parent = null;
camRot = Vector3.right * 90; camRot.z = slots
[curSlot].transform.position.y;
info.gameObject.SetActive(false); selector.gameObject.SetActive(true);
introPanel.SetActive(false); timePanel.SetActive(true);
lockDampButton.SetActive(false);
}
public void ToMode1(SolarOrbit p) //Tapping Planet
{
mode = 1;
infoPlanet = p;
lockDampTmp=VYAngle(Vector3.zero, infoPlanet.transform.position);
lockDampButton.SetActive(true);
transform.parent = p.transform;
curPos = transform.localPosition; camPos=p.transform.position;
curRot.x = Mathf.Repeat(curRot.x,360);
camRot = new Vector3(VYAngle(Vector3.zero, p.transform.position)-90, 0,
Mathf.Max( p.Par [7] * 2f,p.Par [7] + 0.011f));
info.gameObject.SetActive(true); selector.gameObject.SetActive(false);
stat.gameObject.SetActive(false); detail.gameObject.SetActive(false);
slots [curSlot].Fade(false,false); statButton.SetActive(true);
introTxt.text=stat.getName(p.id);
introPanel.SetActive(true); timePanel.SetActive(true);
}
public void ToMode1F(float att, string id) //Special: Tapping Sun
{
mode = 1;
infoPlanet = null;
infoPlanetId = id;
curPos = transform.localPosition;
curRot.x = Mathf.Repeat(curRot.x,360);
camRot = Vector3.forward * att;
info.gameObject.SetActive(true); selector.gameObject.SetActive(false);
stat.gameObject.SetActive(false); detail.gameObject.SetActive(false);
slots [curSlot].Fade(false,false); statButton.SetActive(id=="sun");
introTxt.text=stat.getName(id);
introPanel.SetActive(true); timePanel.SetActive(true);
}
public void ToMode1Back(){ //Back Button on Mode 1
if (mode == 1){
ToMode0();
return;
}
else
mode = 1;
info.gameObject.SetActive(true); selector.gameObject.SetActive(false);
stat.gameObject.SetActive(false); detail.gameObject.SetActive(false);
introPanel.SetActive(true); timePanel.SetActive(true);
}

5
public void ToMode2() //Statistics Button
{
mode = 2;
stat.gameObject.SetActive(true);
if(infoPlanet)
stat.Load(infoPlanet.id,infoPlanet.GetComponent<SolarPlanetCracker>());
else
stat.Load(infoPlanetId,null);

detail.gameObject.SetActive(false);
introPanel.SetActive(false); timePanel.SetActive(false);
}
public void ToMode3() //Detail Button
{
mode = 3;
stat.gameObject.SetActive(false); detail.gameObject.SetActive(true);
if(infoPlanet)
detail.Load(infoPlanet.id);
else
detail.Load(infoPlanetId);
introPanel.SetActive(false); timePanel.SetActive(false);
}

Zoom In-Out (Ganti Slot) Mode 0


public void SwitchSlot(bool Next)
{
slots [curSlot].Fade(false);
curSlot = (int)Mathf.Repeat(curSlot + (Next ? 1 : -1), slots.Length);
slots [curSlot].Fade(true);
selectorTxt.text=slots[curSlot].txt;
camRot.z = slots [curSlot].transform.position.y;
}

Mekanisme Slot
public class SolarSlot : MonoBehaviour
{
public SolarOrbitRenderer[] orbits;
public RectTransform[] buttons;
public bool rayEnabled = false;
public string txt;
public void Fade(bool On, bool dim=true)
{
if(On)
StartCoroutine(fadeOn());
else{
if(dim)
StartCoroutine(dimOff());
else
StartCoroutine(fadeOff());
}
}

IEnumerator fadeOn(){
Color c;Vector3 s;
float m=Time.time,i=0;
while(Time.time<m+0.5f){
i=Mathf.Clamp01((Time.time-m)/0.4f);

c = Color.Lerp(Color.white*.2f,Color.white,i);
s = Vector3.one * (i);
for (int j = 0; j < orbits.Length; j++) {
if(orbits[j])
orbits[j].color = c;

6
buttons[j].localScale = s;
}
yield return null;
}
}
IEnumerator fadeOff(){
Color c;Vector3 s;
float m=Time.time,i=0;
while(Time.time<m+0.5f){
i=Mathf.Clamp01((Time.time-m)/0.4f);

c = Color.Lerp(Color.white,Color.black,i);
s = Vector3.one * ((1-i));
for (int j = 0; j < orbits.Length; j++) {
if(orbits[j])
orbits[j].color = c;
buttons[j].localScale = s;
}
yield return null;
}
}
IEnumerator dimOff(){
Color c;Vector3 s;
float m=Time.time,i=0;
while(Time.time<m+0.5f){
i=Mathf.Clamp01((Time.time-m)/0.4f);

c = Color.Lerp(Color.white,Color.white*.2f,i);
s = Vector3.one * ((1-i));
for (int j = 0; j < orbits.Length; j++) {
if(orbits[j])
orbits[j].color = c;
buttons[j].localScale = s;
}
yield return null;
}
}
public void Return(){
for (int j = 0; j < orbits.Length; j++) {
buttons[j].localScale = Vector3.one;
}
}
}

Swiping Gesture
//Sebuah Event yang merespon Gesture Swipe. respon dikirim kesemua UI dengan
kode 0 sampai 3
public class UISwipe : MonoBehaviour, IEndDragHandler
{
public class SwipeEvent : UnityEvent<int> { }
public SwipeEvent even;
public virtual void OnEndDrag(PointerEventData eventData)
{
Vector2 delta = eventData.position - eventData.pressPosition;
if (delta.sqrMagnitude > 25)
{
if (delta.x > Mathf.Abs(delta.y))
even.Invoke(0); //Swipe Right
else if (delta.y > Mathf.Abs(delta.x))
even.Invoke(1); //Swipe Up
else if (-delta.x > Mathf.Abs(delta.y))
even.Invoke(2); //Swipe Left
7
else if (-delta.y > Mathf.Abs(delta.x))
even.Invoke(3); //Swipe Down
eventData.Use();
}}}

Alih Topik Mode 2 (Window Statistik)


public void PanelNext(){ //Tombol Kanan
RectTransform fr = panels[panelCur];
rep:
panelCur++;
if(panelCur >= panels.Length)
panelCur =0;
if(!panelExist[panelCur])
goto rep;
StartCoroutine( PanelAnimate(fr,panels[panelCur]));
}

public void PanelPrev(){ //Tombol Kiri


RectTransform fr = panels[panelCur];
rep:
panelCur--;
if(panelCur < 0)
panelCur =panels.Length-1;
if(!panelExist[panelCur])
goto rep;
StartCoroutine(PanelAnimate(fr,panels[panelCur]));
}
public void PanelSwipe(int mode) //Respon Swipe
{
if (mode == 2)
PanelNext();
else if (mode == 0)
PanelPrev();
}
IEnumerator PanelAnimate(RectTransform from, RectTransform to){ //Transisi
Antar Panel
if(panelCur == 2 && soc) //Saat Panel ke 3 (Inti), Tampilkan Potongan
Planet
soc.DoCrack();//Lihat Planet Cracking
else if(soc && soc.onCrack)
soc.DoUnCrack();
panelLabel.text = panelStr[panelCur];
to.gameObject.SetActive(true);
Vector3 f=Vector3.one, t=Vector3.one;
float m=Time.time,i=0;
while(Time.time<m+0.5f){
i=(Time.time-m)/0.5f;
f.x=Mathf.SmoothStep(1,0,i);
t.x=1-f.x;
from.localScale=f;
to.localScale=t;
yielfd return null;
}
to.localScale = Vector3.one;
from.gameObject.SetActive(false);
}

8
Alih Topik Mode 3 (Window Detail)
public void PanelNext(){
if(curNode.Count>1){
curIdx++;
if(curIdx >= curNode.Count)
curIdx =0;
StartCoroutine( MoonPanelAnim(curNode[curIdx]));
}
}
public void PanelPrev(){
if(curNode.Count>1){
curIdx--;
if(curIdx < 0)
curIdx =curNode.Count-1;
StartCoroutine(MoonPanelAnim(curNode[curIdx]));
}
}
public void PopSwipe(int mode)
{
if (mode == 2)
PanelNext();
else if (mode == 0)
PanelPrev();
}
public RectTransform container;
IEnumerator MoonPanelAnim(XmlNode cur){
Vector3 x=Vector3.one;
float t=Time.time,i=0;
bool hasC=false;
while(Time.time<t+0.5f){
i=(Time.time-t)/0.5f;
if(i<=0.5f)
x.x = Mathf.SmoothStep(1,-1,i);
if(i>0.5f && !hasC){
image.sprite = images[int.Parse(cur.Attributes["id"].Value)];
title.text = cur.Attributes["title"].Value;

detail.text = cur.InnerText;
com.text = cur.Attributes["caption"].Value;
hasC=true;
}
if(i>0.5f)
x.x = Mathf.SmoothStep(-1,1,i);
transform.localScale= x;
yield return null;
}
transform.localScale = Vector3.one;
}

9
Planet Cracking (Membuka Bagian saat Mode 2, Inti)
public class SolarPlanetCracker : MonoBehaviour
{
public Mesh crackOn;
public Mesh crackOff;
[HideInInspector]
public bool onCrack=false;
public bool isSun=false;
Transform shell;
Quaternion lastRot;
float lastTime;
// Buka Segel Planet
public void DoCrack()
{
Camera.main.GetComponent<SolarController>().onFixedCrack=true;
lastTime=SolarOrbit.timeScale;
SolarOrbit.timeScale=0;
shell.GetComponent<MeshFilter>().mesh=crackOn;
shell.GetChild(0).gameObject.SetActive(true);
shell.GetChild(1).gameObject.SetActive(true);
lastRot=shell.localRotation;
StartCoroutine(fade((isSun?Quaternion.identity:
Quaternion.LookRotation(transform.position))*Quaternion.Euler(0,90,0)));
onCrack=true;
}
// Tutup Lagi
public void DoUnCrack()
{
Camera.main.GetComponent<SolarController>().onFixedCrack=false;
SolarOrbit.timeScale=lastTime;
shell.GetComponent<MeshFilter>().mesh=crackOff;
shell.GetChild(0).gameObject.SetActive(false);
shell.GetChild(1).gameObject.SetActive(false);
StartCoroutine(fade(lastRot));
onCrack=false;
}
IEnumerator fade(Quaternion toRot){
float m=Time.time;
while(Time.time<m+0.4f){

shell.localRotation=Quaternion.Lerp(shell.localRotation,toRot,(Time.time-
m)*2.5f);
yield return null;
}
}
// Update is called once per frame
void Start()
{
shell=isSun?transform: transform.GetChild(0);
}
}

10
Navigasi Kamera 3D – Tata Surya
Navigasi Kamera (Layar) 3D
public float SwipeSpeed = 5f;
Vector3 camPos; Vector3 refPos; Vector3 curPos; //Data Posisi Kamera: Target,
Kecepatan, Sekarang
Vector3 camRot; Vector3 curRot; Vector3 refRot; //Data Rotasi Kamera: Target,
Kecepatan, Sekarang
Vector2 camInput;
public GameObject lockDampButton; //Tombol Lock-View-to-Sun
public bool onFixedCrack=false; //Tampilkan inti?
public bool lockDamp=false; //Aktifkan Lock-View-to-Sun?
float lockDampTmp=0; //Sudut yang dikunci
public void resetLockDamp(){
lockDampTmp=VYAngle(Vector3.zero, infoPlanet.transform.position);
}
public void switchLockDamp(bool value){
lockDamp=value;
}
void LateUpdate()
{
if (mode < 2) //Aktifkan Geser saat mode 0 dan 1
{
Vector2 d;
if (GetInput(ref camInput, out d)) //Respon input Touch
{
camRot += (Vector3)d * Time.unscaledDeltaTime * SwipeSpeed;
camRot.y = Mathf.Clamp(camRot.y, -89.9f, 89.9f);
}

//Apply Transform
if(onFixedCrack)
curRot = Vector3.SmoothDamp(curRot,new
Vector3(VYAngle(Vector3.zero,infoPlanet?
infoPlanet.transform.position:Vector3.forward),0,camRot.z), ref refRot,
speedDamp);
else
curRot = Vector3.SmoothDamp(curRot, camRot, ref refRot, speedDamp);

if (mode > 0) //Letakkan kamera didekat Planet


{
curPos = Vector3.SmoothDamp(curPos, Vector3.zero, ref refPos,
speedDamp);
transform.localPosition = curPos + ( Nav2Rot(curRot));
transform.localRotation = Quaternion.LookRotation(-
transform.localPosition);
if(lockDamp && infoPlanet)
{
float ldNow=VYAngle(Vector3.zero, infoPlanet.transform.position);
camRot.x += -Mathf.DeltaAngle( ldNow,lockDampTmp);
lockDampTmp=ldNow;
}
} else if (mode == 0) //Pusatkan pada Matahari
{
camPos=Vector3.Lerp(camPos,Vector3.zero,Time.deltaTime*2f);
curPos = Vector3.SmoothDamp(curPos, camPos, ref refPos, speedDamp);
transform.position = camPos+ curPos + Nav2Rot(curRot);
transform.LookAt(camPos);
}
}

Vector3 Nav2Rot(Vector3 nav)

11
{
return Quaternion.Euler(nav.y, nav.x, 0) * Vector3.forward * -nav.z;
}

bool GetInput(ref Vector2 pos, out Vector2 delta)


{
Vector2 res = Vector2.zero;
if (Input.mousePresent && Input.GetMouseButton(0))
{
if (Input.GetMouseButtonDown(0))
res = Vector2.zero;
else if (Input.GetMouseButtonUp(0))
res = Vector2.zero;
else
res = (Vector2)Input.mousePosition - pos;
pos = Input.mousePosition;
} else if (Input.touches.Length > 0)
{
if (Input.touches [0].phase == TouchPhase.Began)
res = Vector2.zero;
else if (Input.touches [0].phase == TouchPhase.Canceled || Input.touches
[0].phase == TouchPhase.Ended)
res = Vector2.zero;
else
res = Input.touches [0].position - pos;
pos = Input.touches [0].position;
}
delta = res;
delta.x *= -2;
return res != Vector2.zero;
}

12
Mekanika Orbit Planet
Pre-Computation
Setiap Planet mempunyai data tentang Ciri-ciri orbit dan disimpan dalam :
public float[] Par= new float[]{10,0,1,10,0,0,0,10};
// pericenter, tilt, rotate period, orbit period, inclination, eccentricity, longitudinal
ascending, radius
// 0 1 2 3 4 5 6
7
𝑟 𝜺 𝑇 𝑠 𝑖 𝑒 𝛺 𝑚
Lakukan komputasi saat pertama kali dijalankan :
2𝜍 𝑠
−(1 + 𝑒) 𝑘 = 𝑠𝑟 2 𝛿=
𝜍 = 𝜋𝑟 2√
(1 + 𝑒)2 2(𝑁 − 1)
(−1 + 𝑒) 3

surface = Mathf.Sqrt(-(1 + Par [5]) / Mathf.Pow(-1 + Par [5], 3)) * Mathf.PI *


Par [0] * Par [0];
k = 2 * surface / (Mathf.Pow(1 + Par [5], 2) * Par [3] * Par [0] * Par [0]);
N = 300;
orbitDt = Par [3] / (2 * (N - 1));

ThetaRunge();
time = Random.Range(0, Par [3]); //Waktu Random, dikarenakan tidak mensimulasi
waktu nyata

CosSinOmega [0] = Mathf.Cos(Par [6]);


CosSinOmega [1] = Mathf.Sin(Par [6]);
Sample & Cache setiap Sudut yang dihasilkan dari komputasi (mengurangi sistem Overhead
saat runtime) :

(𝑘1 + 2𝑘2 + 2𝑘3 + 𝑘4 )


𝛼𝑛+1 = 𝛼𝑛 + 𝑓(𝜃) = 𝛿𝑘(1 + cos(𝜃)𝑒)2
6
𝑘1 𝑘3
𝑘1 = 𝑓(𝛼𝑛 ); 𝑘2 = 𝑓 (𝛼𝑛 + ) ; 𝑘3 = 𝑓 (𝛼𝑛 + ) ; 𝑘4 = 𝑓(𝛼𝑛 + 𝑘3 )
2 2

private void ThetaRunge()


{
float w = 0, k1, k2, k3, k4;
for (int i = 0; i < N - 2; i++)
{
k1 = orbitDt * dthdt(w);
k2 = orbitDt * dthdt(w + k1 / 2);
k3 = orbitDt * dthdt(w + k2 / 2);
k4 = orbitDt * dthdt(w + k3);
w = w + (k1 + 2 * k2 + 2 * k3 + k4) / 6;
angleArray [i + 1] = w;
}
angleArray [N - 1] = Mathf.PI;
}

private float dthdt(float th)


{
return k * Mathf.Pow((1 + Par [5] * Mathf.Cos(th)), 2);
}

13
Runtime Computation
Setiap Frame posisi Planet berubah dengan :
void Update()
{
time += Time.deltaTime* timeScale; //Tentukan Waktu
transform.localPosition = ParametricOrbit(ThetaInt(time)); //Tentukan Posisi Planet
if(Par[2]>0)
mesh.Rotate(Vector3.down * 360 * Time.deltaTime * timeScale / Par[2],Space.Self);
//Tentukan Rotasi Planet
}
Tentukan Posisi Sudut Planet setiap frame:

𝛼𝑚𝑖𝑛 − 𝛼𝑚𝑎𝑥 𝑖0 𝛼𝑚𝑎𝑥 − 𝑖1 𝛼𝑚𝑖𝑛


𝜃= 𝑖 +
𝑖0 − 𝑖1 𝑖0 − 𝑖1

𝑡 Mod s
𝑖= ; 𝑖0 = ⌈𝑖⌉; 𝑖1 = ⌊𝑖⌋
𝛿
public float ThetaInt(float t)
{
float theta0 = 0; t = t % Par [3];
if (t <= Par [3] / 2)
{
float i = t / orbitDt;
int i0 = (int)Mathf.Clamp(Mathf.Floor(i), 0, N - 1); int i1 =
(int)Mathf.Clamp(Mathf.Ceil(i), 0, N - 1);
if (i0 == i1)
theta0 = angleArray [i0];
else
theta0 = (angleArray [i0] - angleArray [i1]) / (i0 - i1) * i
+ (i0 * angleArray [i1] - angleArray [i0] * i1) / (i0 - i1);
} else {
t = -t + Par [3];
float i = t / orbitDt;
int i0 = (int)Mathf.Clamp(Mathf.Floor(i), 0, N - 1); int i1 =
(int)Mathf.Clamp(Mathf.Ceil(i), 0, N - 1);
if (i0 == i1)
theta0 = -angleArray [i0] + 2 * Mathf.PI;
else
theta0 = -((angleArray [i0] - angleArray [i1]) / (i0 - i1) * i
+ (i0 * angleArray [i1] - angleArray [i0] * i1) / (i0 - i1)) + 2 *
Mathf.PI;
}
return theta0;
}
Tentukan posisi Vektor terhadap sudut :

𝑟(1 + 𝑒) 𝑟(1 + 𝑒) 𝑋 −𝑖 cos(𝛺) 𝑧 sin(𝛺) 𝑧


𝑥 = cos(𝜃) 𝑧 = sin(𝜃) [ 𝑌 ] [ 𝛺 ] (|
= | 0 | |)
1 + cos(𝜃) 𝑒 1 + cos(𝜃) 𝑒 sin(𝛺) 𝑥 −cos(𝛺) 𝑥
𝑍 0
public Vector3 ParametricOrbit(float th)
{
float Cost = Mathf.Cos(th);
float Sint = Mathf.Sin(th);
float x = (Par [0] * (1 + Par [5])) / (1 + Par [5] * Cost) * Cost;
float z = (Par [0] * (1 + Par [5])) / (1 + Par [5] * Cost) * Sint;
float xp = CosSinOmega [0] * x - CosSinOmega [1] * z;
float yp = CosSinOmega [1] * x + CosSinOmega [0] * z;

return Quaternion.Euler(-Par [4], Par [6], 0) * new Vector3(xp, 0f, yp);


}
14
Visual Design – Tata Surya
Efek Sinar (Flare) Matahari
Atur Intensitas Flare terhadap Jarak dengan Matahari
public float minOff = 2f;
public float maxOff = 1f;
public LensFlare sunFlare;
public float strength = 5f;

void Update()
{
Vector3 heading = sunFlare.transform.position - transform.position;

float dist = Vector3.Dot(heading, transform.forward);

if(dist>minOff)
sunFlare.brightness = strength / Mathf.Pow(dist, 1 / 3f);
else
sunFlare.brightness = (strength / Mathf.Pow(dist, 1 / 3f)) *
Mathf.InverseLerp(maxOff,minOff,dist);
}

Orbit Planet
Render Orbit Planet
public class SolarOrbitRenderer : MonoBehaviour
{
public Material mat;
public Color color;
SolarOrbit PO;
int lineLength;
Vector3[] pos;
void Start()
{
PO = GetComponent<SolarOrbit>();

lineLength =180;
pos = new Vector3[lineLength];
for (int i = 0; i < lineLength; i++) //Komputasi Kemungkinan 180 Titik
Orbit
pos[i] = PO.ParametricOrbit(2 * Mathf.PI / (lineLength - 1) * i);
Camera.onPostRender += DrawGL;
}
void OnDestroy(){
Camera.onPostRender -= DrawGL;
}
void DrawGL(Camera cam) { //Legacy Draw Method
if(isActiveAndEnabled){
mat.SetPass(0);
GL.Begin( GL.LINES );
GL.Color( color );

for(int i = 1; i < pos.Length; i++) {


GL.Vertex3(pos[i-1].x, pos[i-1].y, pos[i-1].z); //Gambar Garis
dari...
GL.Vertex3(pos[i].x, pos[i].y, pos[i].z); //Gambar Garis hingga...
}
GL.End();
}
}
}
15
Navigasi Slider – Alam Semesta
Pusat Kontrol
Kontrol pada Alam Semesta hampir sama seperti Tata Surya, terdiri dari Mode 0 hingga 2.
public class UniverseController : MonoBehaviour {
#region Selector
public RectTransform mainPanel;
internal RectTransform selectedPanel;
public RectTransform materyPanel;
int mode = 0;
public void Back () { //Tombol Kembali
if (mode == 2)
{
StartCoroutine(animRect(materyPanel, false));
StartCoroutine(animRect(selectedPanel,true));
}
else if (mode == 1)
{
StartCoroutine(animRect(selectedPanel, false));
StartCoroutine(animRect(mainPanel, true));
}
else if (mode == 0)
{
Application.LoadLevel(0);
}
mode--;
}
public void EngageTo1(GameObject selected)
{
if(mode==0)
StartCoroutine(animRect(mainPanel, false));
else
StartCoroutine(animRect(materyPanel, false));
mode=1;
selectedPanel = selected.GetComponent<RectTransform>();
StartCoroutine(animRect(selectedPanel, true));

}
public void EngageTo2(int id)
{
mode=2;
StartCoroutine(animRect(selectedPanel, false));
StartCoroutine(animRect(materyPanel, true));
Load(id);
}
IEnumerator animRect(RectTransform t, bool on)
{
if (on)
t.gameObject.SetActive(true);
float m=Time.time,i=0;
while(Time.time<m+0.5f)
{
i=(Time.time-m)/0.5f;
if(on)
t.localScale = new Vector3(Mathf.SmoothStep(0, 1, i), 1, 1);
else
t.localScale = new Vector3(Mathf.SmoothStep(1, 0, i), 1, 1);
yield return null;
}
t.localScale = new Vector3(on?1:0, 1, 1);
if (!on)

16
t.gameObject.SetActive(false);
}
#endregion
#region Animate Matery
[Header("Matery")]
public TextAsset data;
public Text title; public Text detail;
public Transform matT; GameObject lastT;
public RectTransform matT2; GameObject lastT2;
Transform camT; Transform cam;
Vector3 refCamT;
XmlDocument doc; XmlNode docCur;
int NodeId; int NodeCur;
void LoadXML(){
if(doc==null){
doc = new XmlDocument();
doc.LoadXml(data.text); // Muat UniverseDetail.xml
InitMatT();
}
}
void Load(int id){ //Muat Data
if(doc==null)
LoadXML();
docCur = doc.SelectSingleNode("/def/i[@id='" + id + "']");
NodeId = id;
MateryInit();
}
void InitMatT(){ //Clean-up Materi 3D
Transform c;
for (int i = 0; i < matT.childCount; i++)
{
c=matT.GetChild(i);
for (int j = 0; j < c.childCount; j++)
{
c.GetChild(j).gameObject.SetActive(false);
}
}
for (int i = 0; i < matT2.childCount; i++)
{
c=matT2.GetChild(i);
for (int j = 0; j < c.childCount; j++)
{
c.GetChild(j).gameObject.SetActive(false);
}
}
}
IEnumerator animMatF2(Transform F) //Clean-up Materi UI
{
float m = Time.time, i = 0;
bool hasT = false;
while (Time.time < m + 0.5f)
{
i = Mathf.SmoothStep(0,2, (Time.time - m)*2);
if (i < 1)
matT2.localScale = new Vector3(1-i, 1, 1);
if(i>1 && !hasT)
{
hasT = true;
if (lastT2)
lastT2.SetActive(false);
if (F)
{
lastT2 = F.gameObject;
lastT2.SetActive(true);
}
}
17
if (i>1)
matT2.localScale = new Vector3(i-1, 1, 1);
yield return null;
}
matT2.localScale = Vector3.one;
}
public void SwitchMaterySwipe(int n){
if (n == 2)
SwitchMatery(true);
else if(n==0)
SwitchMatery(false);
}
public void SwitchMatery(bool Next){
if (lastT)
lastT.SetActive(false);
NodeCur= (int)Mathf.Repeat(Next?NodeCur+1:NodeCur-
1,docCur.ChildNodes.Count);
Transform F0 = matT.FindChild(NodeId.ToString("00"));
Transform F2 = matT2.FindChild(NodeId.ToString("00"));
if (F0)
{
F0=F0.FindChild(NodeCur.ToString("00"));
if(F0){
lastT=F0.gameObject;
lastT.SetActive(true);
camT= lastT.transform.FindChild("CamPos");
}
}
if (F2)
{
F2=F2.FindChild(NodeCur.ToString("00"));
StartCoroutine(animMatF2(F2));
}
XmlNode n=docCur.ChildNodes[NodeCur];
title.text = n.Attributes["title"].Value;
detail.text = n.InnerText;
}
public void MateryInit() //Setting Pilihan Materi Mode 0 & 1
{
if (lastT)
lastT.SetActive(false);
if (lastT2)
lastT2.SetActive(false);
matT2.localScale = Vector3.one;
NodeCur = 0;
Transform F0 = matT.FindChild(NodeId.ToString("00"));
Transform F2 = matT2.FindChild(NodeId.ToString("00"));
if (F0)
{
F0 = F0.FindChild(NodeCur.ToString("00"));
if (F0)
{
lastT = F0.gameObject;
lastT.SetActive(true);
camT = lastT.transform.FindChild("CamPos");
}
}
if (F2)
{
F2 = F2.FindChild(NodeCur.ToString("00"));
if(F2){
lastT2 = F2.gameObject;
lastT2.SetActive(true);
}
}
XmlNode n = docCur.ChildNodes[NodeCur];
18
title.text = n.Attributes["title"].Value;
detail.text = n.InnerText;
}
public void doPopUp(string txt){

}
void Start(){
cam=Camera.main.transform;
}
void Update(){
if (Input.GetKeyUp(KeyCode.Escape))
Back();
if(camT){ // Selalu Update Posisi Kamera
cam.position=Vector3.SmoothDamp(cam.position,camT.position,ref
refCamT,0.5f);
cam.rotation=Quaternion.Lerp(cam.rotation,camT.rotation,0.1f);
}
}
#endregion
}

19
Slider
Slider berfungsi sebagai Pilihan Deretan panel yang muncul pada halaman utama Alam Semesta.
public class UISlider : MonoBehaviour
{
public RectTransform[] rect;
public GameObject[] target;
public float offset;
public Vector3 offScale;
public int mode2Control = -1;
public Scrollbar Handler;
int curIdx = 0;
void Start()
{
ReAlign(0);
}
public void Scroll(float value)
{
value += 0.5f;
int val = Mathf.FloorToInt(value);
DoPanel(rect[curIdx], Mathf.Clamp(value, curIdx, curIdx + 1) - curIdx);
if (curIdx != val)
ReAlign(val);
curIdx = Mathf.FloorToInt(value);
DoPanel(rect[curIdx], Mathf.Clamp(value, curIdx, curIdx + 1) - curIdx);
rect[curIdx].SetAsLastSibling();
}
void DoPanel(RectTransform panel, float phase)
{
if (phase > 0.5f)
{
phase = (phase - 0.5f) * 2;
panel.localPosition = Vector3.left * offset * (1 - (curIdx * 0.05f)) *
phase;
panel.localScale = Vector3.Lerp(Vector3.one, offScale * (1 + (curIdx *
0.04f)), phase);
}
else
{
phase = 1 - (phase * 2);
panel.localPosition = Vector3.right * offset * (1 - ((rect.Length - 1 -
curIdx) * 0.05f)) * phase;
panel.localScale = Vector3.Lerp(Vector3.one, offScale * (1 +
((rect.Length - 1 - curIdx) * 0.04f)), phase);
}
}

public void DoSwipe(int swipe)


{
if (swipe == 2)
StartCoroutine(SwipeAnim((int)Mathf.Clamp(curIdx + 1, 0, rect.Length -
1)));
else if (swipe == 0)
StartCoroutine(SwipeAnim((int)Mathf.Clamp(curIdx - 1, 0, rect.Length -
1)));
}
public void DoSwipeTo()
{
StartCoroutine(SwipeAnim((int)Mathf.Clamp(Handler.value*(rect.Length-1), 0,
rect.Length - 1),false));
}
IEnumerator SwipeAnim(int idxTo,bool animHandle=true)
{
float cur = curIdx,now = idxTo,m=Time.unscaledTime,i=0;

20
if(animHandle)
Handler.value = now / (rect.Length-1);
while (Time.unscaledTime<m+0.5f){
i=(Time.unscaledTime-m)/0.5f;
Scroll(Mathf.SmoothStep(cur, now, i));
yield return null;
}
Scroll(Mathf.SmoothStep(cur, now, 1));
}
void ReAlign(int now)
{
for (int i = 0; i < rect.Length; i++)
{
if (i < now)
{
rect[i].localPosition = Vector3.left * offset * (1 - (i * 0.05f));
rect[i].localScale = offScale * (1 + (i * 0.04f));
}
else if (i > now)
{
rect[i].localPosition = Vector3.right * offset * (1 - ((rect.Length
- 1 - i) * 0.05f));
rect[i].localScale = offScale * (1 + ((rect.Length - 1 - i) *
0.04f));
}

}
}
public void PopTarget(int idx)
{
if (mode2Control >= 0)

transform.parent.GetComponent<UniverseController>().EngageTo1(target[idx].gameOb
ject);
}
public void PopMatery(int id)
{
if (mode2Control >= 0)
transform.parent.GetComponent<UniverseController>().EngageTo2(id);
}}

21
Animator – Alam Semesta
Disini semua Script Animator, yaitu skrip yang dikhususkan untuk menjalankan berbagai macam
fungsi Animasi untuk menjalankan Ilustrasi 3D Menarik pada Alam Semesta.

ObjForcer
public class ObjForcer : MonoBehaviour
{
public Vector3 speed=Vector3.zero;
public Space orientation;
public bool linear=true;
public AnimationCurve curve=AnimationCurve.EaseInOut(0,0,1,1);
public float time=5;
public bool restoreOnDisable=true;
float tim; Vector3 b;
void Update(){
if(linear)
transform.Translate(speed*Time.deltaTime,orientation);
else{
tim+=Time.deltaTime;

transform.Translate(speed*Time.deltaTime*curve.Evaluate(tim/time),orientation);
}
}
void Awake(){
b=orientation==Space.Self?transform.localPosition:transform.position;
}
void OnEnable(){
tim=0;
if(restoreOnDisable)
{
if(orientation==Space.Self)
transform.localPosition=b;
else
transform.position=b;
}
}
void OnDisable(){}
}

ObjImageFiller
public class ObjImageFiller : MonoBehaviour
{
public Image target;
public float from=0;
public float to=1;
public float time = 5;
public bool linear = true;
public AnimationCurve inter = AnimationCurve.EaseInOut(0, 0, 1, 1);
[Range(0, 2)]
public int loopMode = 2;
float tim = 0;
bool invert = false;
// Use this for initialization
void OnEnable()
{
tim = 0;
}
void Reset()
{
target = GetComponent<Image>();
}
// Update is called once per frame
22
void Update()
{
if (!invert)
tim += Time.deltaTime;
else
tim -= Time.deltaTime;
if (tim < time)
{
if (tim < 0)
invert = false;
float ir;
if (linear)
ir = Mathf.Lerp(from, to, tim / time);
else
ir = Mathf.Lerp(from, to, inter.Evaluate(tim / time));
target.fillAmount=ir;
} else {
if (loopMode == 0)
target.fillAmount = linear? to:(inter.Evaluate(1)*to);
if (loopMode == 1)
tim = 0;
else if (loopMode == 2)
invert = true;
}}}

ObjInvoker
public class ObjInvoker : MonoBehaviour
{
public MonoBehaviour comp;
public bool Enable=true;
public float delay=1;
public bool restoreOnDisable=true;
bool lastB;
void OnEnable()
{
if(restoreOnDisable)
comp.enabled=lastB;
lastB=comp.enabled;
Invoke("Go",delay);
}
void Awake(){
lastB=comp.enabled;
}
void Go()
{
comp.enabled=Enable;
}}

ObjLookAt
public class ObjLookAt : MonoBehaviour{
public Transform target;
public bool isUI=true;
void Update(){
transform.LookAt(target);
if(isUI)
transform.Rotate(0,180,0,Space.Self);
}
void Reset(){
target=Camera.main.transform;
}}

ObjMover
public class ObjMover : MonoBehaviour

23
{
public Vector3 from;
public Vector3 to;
public float time=5;
public bool linear=true;
public bool isRotate = false;
public AnimationCurve inter=AnimationCurve.EaseInOut(0,0,1,1);
public Space space;
[Range(0,2)]
public int loopMode=2;
float tim=0;
bool invert=false;
void OnEnable()
{ tim=0; }
void Update()
{
if(!invert)
tim+=Time.deltaTime;
else
tim-=Time.deltaTime;
if(tim<time){
if(tim<0)
invert=false;
Vector3 ir;
if(linear)
ir=Vector3.Lerp(from,to,tim/time);
else
ir=Vector3.Lerp(from,to, inter.Evaluate(tim/time));
if (isRotate)
{
if (space == Space.Self)
transform.localEulerAngles = ir;
else
transform.eulerAngles = ir;
} else {
if (space == Space.Self)
transform.localPosition = ir;
else
transform.position = ir;
}}else{
if (loopMode == 0)
{
Vector3 ia=linear? to :inter.Evaluate(1)*to;
if (isRotate)
{
if (space == Space.Self)
transform.localEulerAngles = ia;
else
transform.eulerAngles = ia;
} else {
if (space == Space.Self)
transform.localPosition = ia;
else
transform.position = ia;
}}
else if (loopMode == 1)
tim = 0;
else if (loopMode == 2)
invert = true;
}}}

ObjParentChanger
public class ObjParentChanger : MonoBehaviour
{
public Transform parent;
24
public float delay=1;
public bool restoreOnDisable=true;
Transform lastP;
void OnEnable()
{
lastP=transform.parent;
Invoke("Go",delay);
}
void OnDisable(){
if(restoreOnDisable)
transform.parent=lastP;
}

// Update is called once per frame


void Go()
{
transform.parent=parent;
}
}

ObjPin2D
public class ObjPin2D : MonoBehaviour {

public Transform target;

// Update is called once per frame


void LateUpdate () {
Vector3 n = Camera.main.WorldToScreenPoint(target.position);
transform.position = (Vector2)n * (n.z > 0?1:-1);
}
}

ObjPinPos
public class ObjPinPos : MonoBehaviour
{
public Transform target;
public Vector3 offset;
void Update(){
#if UNITY_EDITOR
if(target)
#endif
transform.position = target.position+offset;
}
}

ObjPosSwitch
public class ObjPosSwitch : MonoBehaviour
{
public Transform[] target;
int cur=0;
Vector3 posSpeed = Vector3.zero;
// Use this for initialization
void OnEnable()
{
cur=0;
}
public void Switch(bool Next)
{
cur = (int) Mathf.Repeat(cur + (Next ? 1 : -1), target.Length);
}
// Update is called once per frame
void Update()
{

25
transform.position = Vector3.SmoothDamp(transform.position,
target[cur].position, ref posSpeed, 0.3f);
transform.rotation = Quaternion.Lerp(transform.rotation,
target[cur].rotation, 0.1f);
}
}

ObjRotator
public class ObjRotator : MonoBehaviour{
public Vector3 speed=Vector3.up*30;
public Space orientation;
public bool linear=true;
public AnimationCurve curve=AnimationCurve.EaseInOut(0,0,1,1);
public float time=5;
public bool restoreOnDisable=true;
public bool useTimeScale=false;
float tim;
Quaternion b;
void Update(){
if(useTimeScale){
if(linear)

transform.Rotate(speed*Time.deltaTime*SolarOrbit.timeScale,orientation);
else{
tim+=Time.deltaTime*SolarOrbit.timeScale;

transform.Rotate(speed*Time.deltaTime*SolarOrbit.timeScale*curve.Evaluate(tim/ti
me),orientation);
}
}else{
if(linear)
transform.Rotate(speed*Time.deltaTime,orientation);
else{
tim+=Time.deltaTime;

transform.Rotate(speed*Time.deltaTime*curve.Evaluate(tim/time),orientation);
}
}
}
void OnEnable(){
if(restoreOnDisable)
{
if(orientation==Space.Self)
transform.localRotation=b;
else
transform.rotation=b;
}
tim=0;
}
void Awake(){
b=orientation==Space.Self?transform.localRotation:transform.rotation;
}

void OnDisable(){

ObjScaler
public class ObjScaler : MonoBehaviour
{
public Vector3 from=Vector3.zero;
public Vector3 to=Vector3.one;
26
public float time=5;
public bool linear=true;
public AnimationCurve inter=AnimationCurve.EaseInOut(0,0,1,1);
[Range(0,2)]
public int loopMode=2;
float tim=0;
bool invert=false;
// Use this for initialization
void OnEnable()
{
tim=0;
}
void Update()
{
if(!invert)
tim+=Time.deltaTime;
else
tim-=Time.deltaTime;
if(tim<time){
if(tim<0)
invert=false;
Vector3 ir;
if(linear)
ir=Vector3.Lerp(from,to,tim/time);
else
ir=Vector3.Lerp(from,to, inter.Evaluate(tim/time));
transform.localScale=ir;
}else{
if(loopMode==1)
tim=0;
else if(loopMode==2)
invert=true;
}
}
}

ObjStepRotate
public class ObjStepRotate : MonoBehaviour {
public float stepTime=0.1f;
public Vector3 stepRotate;
float tim;
// Use this for initialization

// Update is called once per frame


void Update () {
tim += Time.deltaTime;
if (tim > stepTime)
{
transform.Rotate(stepRotate);
tim-=stepTime;
}
}
}

ObjTextChanger
public class ObjTextChanger : MonoBehaviour{
public string[] texts;
public float[] delays;
public bool PlayOnEnable=true;
public float maxTime=5;
[Range(0,2)]
public int loopMode = 2;
Text txt;
float time;
27
bool invert = false;
int lastIdx=-1;
void OnEnable(){
if(PlayOnEnable){
time=0;
lastIdx=-1;
}
}
public void Play(){
time=0;
lastIdx=-1;
}
void Start(){
txt = GetComponent<Text>();
}
void Update(){
if (invert || time < maxTime)
{
if (invert)
time -= Time.deltaTime;
else
time += Time.deltaTime;
if (time < 0)
invert = false;
if (invert)
{
if ( lastIdx -1 >=0 && time < delays[lastIdx])
{
lastIdx--;
txt.text = texts[lastIdx];
}
}
else {
if (delays.Length > lastIdx + 1 && time > delays[lastIdx + 1])
{
lastIdx++;
txt.text = texts[lastIdx];
}
}
}else
{
if (loopMode == 1)
{
time = 0;
lastIdx = -1;
}
else if (loopMode == 2)
{
invert = true;
txt.text = texts[lastIdx];
//lastIdx--;
}
}
}
}

ObjTextNumeric
public class ObjTextNumeric : MonoBehaviour
{
public float from=0;
public float to=1;
public float time=5;
public bool linear=true;
Text txt;
public AnimationCurve inter=AnimationCurve.EaseInOut(0,0,1,1);
28
[Range(0,2)]
public int loopMode=2;
public string format="0.0";
float tim=0;
bool invert=false;
// Use this for initialization
void OnEnable()
{
tim=0;
txt=GetComponent<Text>();
}
// Update is called once per frame
void Update()
{
if(!invert)
tim+= Time.deltaTime;
else
tim-= Time.deltaTime;
if(tim<time){
if(tim<0)
invert=false;
float ir;
if(linear)
ir=Mathf.Lerp(from,to,tim/time);
else
ir=Mathf.Lerp(from,to, inter.Evaluate(tim/time));
txt.text=ir.ToString(format);
}else{
if(loopMode==0)
txt.text = to.ToString(format);
if (loopMode==1)
tim=0;
else if(loopMode==2)
invert=true;
}
}
}

ObMatColor
public class ObMatColor : MonoBehaviour
{
public Gradient grad;
public Material mat;
public string str;
public float time=5;
public bool linear=true;
public AnimationCurve inter=AnimationCurve.EaseInOut(0,0,1,1);
[Range(0,2)]
public int loopMode=2;
float tim=0;
bool invert=false;
// Use this for initialization
void OnEnable()
{
tim=0;
if (mat == null)
mat = GetComponent<MeshRenderer>().material;
}

// Update is called once per frame


void Update()
{
if(!invert)
tim+=Time.deltaTime;
else
29
tim-=Time.deltaTime;
if(tim<time){
if(tim<0)
invert=false;
Color ir;
if(linear)
ir=grad.Evaluate(tim/time);
else
ir=grad.Evaluate(inter.Evaluate(tim/time));
mat.SetColor(str,ir);
}else{
if(loopMode==1)
tim=0;
else if(loopMode==2)
invert=true;
}
}
}

ObMatSize
public class ObMatSize : MonoBehaviour
{
public float from;
public float to;
public Material mat;
public string str;
public float time=5;
public bool linear=true;
public AnimationCurve inter=AnimationCurve.EaseInOut(0,0,1,1);
[Range(0,2)]
public int loopMode=2;
float tim=0;
bool invert=false;
// Use this for initialization
void OnEnable()
{
tim=0;
if (mat == null)
mat = GetComponent<MeshRenderer>().material;
}

// Update is called once per frame


void Update()
{
if(!invert)
tim+=Time.deltaTime;
else
tim-=Time.deltaTime;
if(tim<time){
if(tim<0)
invert=false;
float ir;
if(linear)
ir=Mathf.Lerp(from,to,tim/ time);
else
ir= Mathf.Lerp(from, to, inter.Evaluate(tim/time));
mat.SetFloat(str,ir);
}else{
if(loopMode==1)
tim=0;
else if(loopMode==2)
invert=true;
}
}}

30

You might also like