29
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UnityAdvent Calendar 2013

Day 15

Unity4.3新機能とか Haxeで何かつくったはなし。(後編 : 3時間程度で2Dのクソゲーを作た。 )

Last updated at Posted at 2013-12-15

はいはい。前編はHaxe Advent Calendarで (http://qiita.com/nobkz/items/ce6bbf56d0f0cbad2e13 )やりました。今回は後編を書きます。

(ちなみに、福岡で開催されている、八時間作品制作会で、3時間程度かけてつくりました。のこりの5時間は歯医者とか音楽制作とかに費しますた。)

ちなみに今回作ったゲームはこちらです。

Haxe + Unity3d 後編

画像素材の準備

まずこんな感じで準備

sample.png

ちなみにPagesでテキトーに図形配置して、選択してCommand + Cでコピー

スクリーンショット 2013-12-15 23.09.43.png

んで、プレビューappでクリップボードから新規作成

スクリーンショット 2013-12-15 23.12.02.png

で作りますた。

Sprite EditorでSprite分割

んで、準備した画像をUnityへドラッグアンドドロップして、追加した画像を選択Inspectorで

スクリーンショット 2013-12-15 23.13.38.png

こんな感じに設定する。 (Texture type -> Sprite、 Sprite Mode -> Multiple)に選択する。

んでSprite Editorボタンをクリックして、

スクリーンショット 2013-12-15 23.16.56.png

んで、Sliceして、Applyする。

スクリーンショット 2013-12-15 23.17.44.png

するとSpriteが分割されます。

スクリーンショット 2013-12-15 23.21.23.png

Spriteを配置、Animationを作る

さて、できたSpriteをこんな感じでScene画面に配置します。

Scene画面はこんな感じ

スクリーンショット 2013-12-15 23.19.08.png

階層構造はこんな感じ

スクリーンショット 2013-12-15 23.20.56.png

さてここで、Animationを付けていくのですが、ここで注意なのが、 Sceneに置いているGameObjectの同じ名前のオブジェクトを複数作らないでください 。それをするとAnimation Editorで困ります。

んで、HierarchyのHumanを選択したまま、Window -> Animationを選択します。

スクリーンショット 2013-12-15 23.27.17.png

そうするとAnimation Editorが出てきてキーフレームでAnimationを作成できます。

スクリーンショット 2013-12-15 23.28.06.png

今回は、

  • 走るアニメーション
  • 棒人間が壊れるアニメーション
  • ゴールした時のアニメーション

スクリーンショット 2013-12-15 23.30.12.png

を準備しました。

Mecanimでアニメーション遷移の管理

さて、Mecanimでアニメーション遷移を管理します。

window -> Animatorを選択

スクリーンショット 2013-12-15 23.32.38.png

すると、先程作ったAnimationClipが配置されて、いるはずです。

そしてこんな感じに設定しますた。

スクリーンショット 2013-12-15 23.31.32.png

んで各遷移(矢印の)Inspector設定はこんな感じです。

Human -> break

スクリーンショット 2013-12-15 23.34.56.png

Human -> goal

スクリーンショット 2013-12-15 23.35.01.png

物理演算設定

  • Humanにはbox Collider2dとRigidBody
  • あとテキトーにCollider2dは設定

スクリプティング

だいたいHaxeで書きますた。

HumanController.hx
package ;
import unityEngine.MonoBehaviour;
import unityEngine.Transform;
import unityEngine.Time;
import unityEngine.Vector3;
import unityEngine.GameObject;
import unityEngine.Animator;
using UnityHelper;

class HumanController extends MonoBehaviour{
	public var speed : Single;
	public var force : unityEngine.Vector2;
	public var anim : Animator;

	public function Update(){
		if( !this.anim.GetBool("breaked") &&  !this.anim.GetBool("goal") ){
			this.getTransform().Translate(speed, 0.0, 0.0);
			if( unityEngine.Input.GetMouseButton(0) ){
				untyped __cs__("this.rigidbody2D.AddForce(force)");
			}
		}
	}

	public function breaking(){
		unityEngine.Application.LoadLevel("Start");
	}
}
Box.hx
package;

import unityEngine.MonoBehaviour;
import unityEngine.Collision2D;

class Box extends MonoBehaviour{
	public function OnCollisionEnter2D(coll : Collision2D){
		var humanController : HumanController =	coll.gameObject.GetComponent();
		humanController.anim.SetBool("breaked",true);
	}
}
Goal.hx
package;

import unityEngine.MonoBehaviour;
import unityEngine.Collision2D;

class Goal extends MonoBehaviour{
	public function OnTriggerEnter2D(coll : Collision2D){
		var humanControlelr : HumanController = coll.gameObject.GetComponent();
		humanControlelr.anim.SetBool("goal",true);
	}
}

Animatorと、Collider2Dのクラスがhx-unityに実装されてなかった!

なので必要最小限のexternを書いた。

Animator.hx
package unityEngine;
@:native("UnityEngine.Animator") extern class Animator extends Behaviour {
	function GetBool(name:String) : Bool;
	function SetBool(name:String, value:Bool) : Void;
}
Collider2D.hx
package unityEngine;
@:native("UnityEngine.Collision2D") extern class Collision2D extends Behaviour {
	 var gameObject : unityEngine.GameObject;
}

今度、Unity4.3の分の修正して、プルリク送っておくか...

あとHxmlとか

一応、こんな感じになった。

build.hxml
-lib unity3d
-cp src/
-cs cs
-D no-compilation
HumanController
CameraScript
Opening
Box
Goal

あと、こまごま色々やって完成!!!

えっとあとは、

  • パラメータの調節 ( 大してやってない。 )
  • Title画面つくって、Scene遷移とか

やって完成。

まとめ。

Unity3dの2D機能について

個人的には2Dは以前のバージョンのUnityよりかた作りやすくなっていると思います。

Haxe と Unity3dについて

よかった点

  • 意外と書きやすかった。Haxeのコンパイラの補完機能のお陰
  • 型推論などのHaxeの言語機能が素晴しい

悪かった点

  • ライブラリが不十分なところもあるので、ところどころextern書かないと行けない。

以上です。ここまで読んでくれた方ありがとうございました!

追記

あ、Animation Editor上で、Event呼び出す設定もついでに。

スクリーンショット 2013-12-16 0.22.43.png

スクリーンショット 2013-12-16 0.22.55.png

これで、Humanのbreaking()メソッドが呼びだされます。

追記2:HaxeをビルドしたC#のソース

こんな感じ。読めなくはない。

HumanController.cs

#pragma warning disable 109, 114, 219, 429, 168, 162
public  class HumanController : global::UnityEngine.MonoBehaviour, global::haxe.lang.IHxObject 
{
	public    HumanController(global::haxe.lang.EmptyObject empty) : base()
	{
		unchecked 
		{
		}
		#line default
	}
	
	
	public    HumanController() : base()
	{
		unchecked 
		{
		}
		#line default
	}
	
	
	public static   object __hx_createEmpty()
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			return new global::HumanController(((global::haxe.lang.EmptyObject) (global::haxe.lang.EmptyObject.EMPTY) ));
		}
		#line default
	}
	
	
	public static   object __hx_create(global::Array arr)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			return new global::HumanController();
		}
		#line default
	}
	
	
	public  float speed;
	
	public  global::UnityEngine.Vector2 force;
	
	public  global::UnityEngine.Animator anim;
	
	public virtual   void Update()
	{
		unchecked 
		{
			#line 15 "src/HumanController.hx"
			if ((  ! (this.anim.GetBool("breaked"))  &&  ! (this.anim.GetBool("goal"))  )) 
			{
				#line 17 "src/HumanController.hx"
				((global::UnityEngine.Transform) (global::haxe.lang.Runtime.getField(this, "transform", 1167273324, true)) ).Translate(((float) (this.speed) ), ((float) (0.0) ), ((float) (0.0) ), ((global::UnityEngine.Space) (default(global::UnityEngine.Space)) ));
				if (global::UnityEngine.Input.GetMouseButton(0)) 
				{
					#line 18 "src/HumanController.hx"
					this.rigidbody2D.AddForce(force);
				}
				
			}
			
		}
		#line default
	}
	
	
	public virtual   void breaking()
	{
		unchecked 
		{
			#line 24 "src/HumanController.hx"
			global::UnityEngine.Application.LoadLevel("Start");
		}
		#line default
	}
	
	
	public virtual   bool __hx_deleteField(string field, int hash)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			return false;
		}
		#line default
	}
	
	
	public virtual   object __hx_lookupField(string field, int hash, bool throwErrors, bool isCheck)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			if (isCheck) 
			{
				#line 10 "src/HumanController.hx"
				return global::haxe.lang.Runtime.undefined;
			}
			 else 
			{
				#line 10 "src/HumanController.hx"
				if (throwErrors) 
				{
					#line 10 "src/HumanController.hx"
					throw global::haxe.lang.HaxeException.wrap("Field not found.");
				}
				 else 
				{
					#line 10 "src/HumanController.hx"
					return default(object);
				}
				
			}
			
		}
		#line default
	}
	
	
	public virtual   double __hx_lookupField_f(string field, int hash, bool throwErrors)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			if (throwErrors) 
			{
				#line 10 "src/HumanController.hx"
				throw global::haxe.lang.HaxeException.wrap("Field not found or incompatible field type.");
			}
			 else 
			{
				#line 10 "src/HumanController.hx"
				return default(double);
			}
			
		}
		#line default
	}
	
	
	public virtual   object __hx_lookupSetField(string field, int hash, object @value)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			throw global::haxe.lang.HaxeException.wrap("Cannot access field for writing.");
		}
		#line default
	}
	
	
	public virtual   double __hx_lookupSetField_f(string field, int hash, double @value)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			throw global::haxe.lang.HaxeException.wrap("Cannot access field for writing or incompatible type.");
		}
		#line default
	}
	
	
	public virtual   double __hx_setField_f(string field, int hash, double @value, bool handleProperties)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			switch (hash)
			{
				case 23697287:
				{
					#line 10 "src/HumanController.hx"
					this.speed = ((float) (@value) );
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				default:
				{
					#line 10 "src/HumanController.hx"
					return this.__hx_lookupSetField_f(field, hash, @value);
				}
				
			}
			
		}
		#line default
	}
	
	
	public virtual   object __hx_setField(string field, int hash, object @value, bool handleProperties)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			switch (hash)
			{
				case 1575675685:
				{
					#line 10 "src/HumanController.hx"
					this.hideFlags = ((global::UnityEngine.HideFlags) (@value) );
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				case 1224700491:
				{
					#line 10 "src/HumanController.hx"
					this.name = global::haxe.lang.Runtime.toString(@value);
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				case 5790298:
				{
					#line 10 "src/HumanController.hx"
					this.tag = global::haxe.lang.Runtime.toString(@value);
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				case 2117141633:
				{
					#line 10 "src/HumanController.hx"
					this.enabled = ((bool) (@value) );
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				case 896046654:
				{
					#line 10 "src/HumanController.hx"
					this.useGUILayout = ((bool) (@value) );
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				case 1081181713:
				{
					#line 10 "src/HumanController.hx"
					this.anim = ((global::UnityEngine.Animator) (@value) );
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				case 76853739:
				{
					#line 10 "src/HumanController.hx"
					this.force = ((global::UnityEngine.Vector2) (@value) );
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				case 23697287:
				{
					#line 10 "src/HumanController.hx"
					this.speed = ((float) (global::haxe.lang.Runtime.toInt(@value)) );
					#line 10 "src/HumanController.hx"
					return @value;
				}
				
				
				default:
				{
					#line 10 "src/HumanController.hx"
					return this.__hx_lookupSetField(field, hash, @value);
				}
				
			}
			
		}
		#line default
	}
	
	
	public virtual   object __hx_getField(string field, int hash, bool throwErrors, bool isCheck, bool handleProperties)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			switch (hash)
			{
				case 1635357710:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("DontDestroyOnLoad"), ((int) (1635357710) ))) );
				}
				
				
				case 1003238327:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("DestroyImmediate"), ((int) (1003238327) ))) );
				}
				
				
				case 1909937370:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("Destroy"), ((int) (1909937370) ))) );
				}
				
				
				case 304123084:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("ToString"), ((int) (304123084) ))) );
				}
				
				
				case 276486854:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetInstanceID"), ((int) (276486854) ))) );
				}
				
				
				case 1575675685:
				{
					#line 10 "src/HumanController.hx"
					return this.hideFlags;
				}
				
				
				case 1224700491:
				{
					#line 10 "src/HumanController.hx"
					return this.name;
				}
				
				
				case 2134927590:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("BroadcastMessage"), ((int) (2134927590) ))) );
				}
				
				
				case 139469119:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("SendMessage"), ((int) (139469119) ))) );
				}
				
				
				case 294420221:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("SendMessageUpwards"), ((int) (294420221) ))) );
				}
				
				
				case 89600725:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("CompareTag"), ((int) (89600725) ))) );
				}
				
				
				case 2122408236:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetComponents"), ((int) (2122408236) ))) );
				}
				
				
				case 967979664:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetComponentsInChildren"), ((int) (967979664) ))) );
				}
				
				
				case 1328964235:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetComponentInChildren"), ((int) (1328964235) ))) );
				}
				
				
				case 1723652455:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetComponent"), ((int) (1723652455) ))) );
				}
				
				
				case 5790298:
				{
					#line 10 "src/HumanController.hx"
					return this.tag;
				}
				
				
				case 2117141633:
				{
					#line 10 "src/HumanController.hx"
					return this.enabled;
				}
				
				
				case 1856815770:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("StopAllCoroutines"), ((int) (1856815770) ))) );
				}
				
				
				case 2084823382:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("StopCoroutine"), ((int) (2084823382) ))) );
				}
				
				
				case 987108662:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("StartCoroutine"), ((int) (987108662) ))) );
				}
				
				
				case 602588383:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("IsInvoking"), ((int) (602588383) ))) );
				}
				
				
				case 757431474:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("CancelInvoke"), ((int) (757431474) ))) );
				}
				
				
				case 1641152943:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("InvokeRepeating"), ((int) (1641152943) ))) );
				}
				
				
				case 1416948632:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("Invoke"), ((int) (1416948632) ))) );
				}
				
				
				case 896046654:
				{
					#line 10 "src/HumanController.hx"
					return this.useGUILayout;
				}
				
				
				case 1825712515:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("breaking"), ((int) (1825712515) ))) );
				}
				
				
				case 999946793:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("Update"), ((int) (999946793) ))) );
				}
				
				
				case 1081181713:
				{
					#line 10 "src/HumanController.hx"
					return this.anim;
				}
				
				
				case 76853739:
				{
					#line 10 "src/HumanController.hx"
					return this.force;
				}
				
				
				case 23697287:
				{
					#line 10 "src/HumanController.hx"
					return this.speed;
				}
				
				
				default:
				{
					#line 10 "src/HumanController.hx"
					return this.__hx_lookupField(field, hash, throwErrors, isCheck);
				}
				
			}
			
		}
		#line default
	}
	
	
	public virtual   double __hx_getField_f(string field, int hash, bool throwErrors, bool handleProperties)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			switch (hash)
			{
				case 23697287:
				{
					#line 10 "src/HumanController.hx"
					return ((double) (this.speed) );
				}
				
				
				default:
				{
					#line 10 "src/HumanController.hx"
					return this.__hx_lookupField_f(field, hash, throwErrors);
				}
				
			}
			
		}
		#line default
	}
	
	
	public virtual   object __hx_invokeField(string field, int hash, global::Array dynargs)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			switch (hash)
			{
				case 1416948632:case 1641152943:case 757431474:case 602588383:case 987108662:case 2084823382:case 1856815770:case 1723652455:case 1328964235:case 967979664:case 2122408236:case 89600725:case 294420221:case 139469119:case 2134927590:case 276486854:case 304123084:case 1909937370:case 1003238327:case 1635357710:
				{
					#line 10 "src/HumanController.hx"
					return global::haxe.lang.Runtime.slowCallField(this, field, dynargs);
				}
				
				
				case 1825712515:
				{
					#line 10 "src/HumanController.hx"
					this.breaking();
					#line 10 "src/HumanController.hx"
					break;
				}
				
				
				case 999946793:
				{
					#line 10 "src/HumanController.hx"
					this.Update();
					#line 10 "src/HumanController.hx"
					break;
				}
				
				
				default:
				{
					#line 10 "src/HumanController.hx"
					return ((global::haxe.lang.Function) (this.__hx_getField(field, hash, true, false, false)) ).__hx_invokeDynamic(dynargs);
				}
				
			}
			
			#line 10 "src/HumanController.hx"
			return default(object);
		}
		#line default
	}
	
	
	public virtual   void __hx_getFields(global::Array<object> baseArr)
	{
		unchecked 
		{
			#line 10 "src/HumanController.hx"
			baseArr.push("hideFlags");
			#line 10 "src/HumanController.hx"
			baseArr.push("name");
			#line 10 "src/HumanController.hx"
			baseArr.push("tag");
			#line 10 "src/HumanController.hx"
			baseArr.push("enabled");
			#line 10 "src/HumanController.hx"
			baseArr.push("useGUILayout");
			#line 10 "src/HumanController.hx"
			baseArr.push("anim");
			#line 10 "src/HumanController.hx"
			baseArr.push("force");
			#line 10 "src/HumanController.hx"
			baseArr.push("speed");
		}
		#line default
	}
	
	
}

追記3:

あしたは、@GRGSIBERIAさんです。よろしくお願いします。

29
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?