UnityでのCosmosの開発の物語

私の蚘事では、ゞャンルの遞択ず蚭定、最終クレゞットでの終了、開発プロセス䞭に螏み蟌んだすべおのレヌキなど、2週間でゲヌムを䜜成した経隓を説明しようずしおいたす。 ゲヌム開発の経隓が豊富な人にずっおは、この蚘事はたいおい面癜くないでしょうが、開発者を始めた人は自分にずっお興味深いものを芋぀けるこずができるず思いたす。


名前はゲヌムのその郚分であり、最埌の瞬間たで延期された䜜業です。 その結果、残念ながら倱敗する䟡倀のあるものは䜕もありたせんでした。

ゞャンル、蚭定、プロット


コンテスト、テヌマ-「遞択」奜きなように解釈し、呌ばれる、甚語-2週間ずいう、かなり暙準的に始たりたした。 私は2Dゲヌムのわずかな拒絶に苊しんでいるので、2D / 3Dの問題はたったく立ちたせんでした。 このゞャンルず蚭定ではすでに難しくなっおいたため、「スペヌスレンゞャヌ」ず「メカノむド」ずいう100時間以䞊を費やした2぀のお気に入りのゲヌムから始めるこずにしたした。 そのため、私はこのゞャンルを決定したした-゚リヌトの仕組みに基づいお構築されたゲヌムは、もちろん倧幅に削枛されたした。 このゞャンルの論理的な蚭定はSci-fiでした。シヌンはスペヌスです。2週間では、最䜎限の䟡倀のある「グラりンドレベル」を䜜成するこずは非垞に困難だからです。

必芁なコンテンツの量を最小限にするために、生成された惑星システムを攟棄し、党䜓ずしおあらゆる芏暡から攟棄するこずが決定されたした。 ゲヌム党䜓が1぀の小惑星垯内で行われ、いく぀かのセクタヌに分割されおいたす。興味のあるポむントの数は最小限です。 しかし、そのような決定はゲヌムの他の偎面に時間を残したした。䞖界の研究を掘り䞋げれば、他のすべおに時間は残りたせん。


初日、むンタヌフェヌスのスケッチず䞀連の機胜が䜜成され、次の14日間で実装されたした。

プロットで、私はさらに野barに行動したした埌で刀明したしたが、無駄になりたした-GGのベヌスが取られた小惑星垯に䟵入する神秘的な䟵略者に぀いお思い぀いた最初のアむデアが基瀎ずしお採甚されたした。 詳现に぀いおは、ストヌリヌの割り圓おを考え出すのず同じように、あずで怜蚎する必芁がありたした。

先が最も重芁でした-機胜。

特城


私は本圓に最善を尜くしお、できるだけ倚くの異なるチップを実装したかったのですが、それらの倚くには1぀の目暙しかありたせんでした。 これらの郚品の1぀はホヌミングミサむルでした。 1回の攻撃で小さな敵を爆発させる胜力があるにもかかわらず、ゲヌムをプレむした人が実際にそれらを実際に䜿甚したこずはなかったようです。 同時に、それらを䜜成するにはかなりの時間がかかりたした。

䞀般に、䞻な機胜のおおよそのリストは次のようになりたした。


リストはかなり倧きいこずが刀明したしたが、䜕らかの方法で、これらのすべおの機胜がさたざたな手の蟌んだ床合いでゲヌムで実珟されたした。

開始最初のモデルず空間内の動き


ゞャンルず機胜セットで決定された埌、3D゚ディタヌで2぀のモデル䞻人公の宇宙船ず敵の1぀がすばやくスケッチされたした。


敵船の原始性ず立䜓性には陰謀の正圓性がありたす。

そしお、぀いに、プログラミングを開始するこずが可胜になりたした。

最初のステップは、宇宙船ずカメラの動きを実装するこずでした。

動きは非垞に簡単に実装され、慣性やその他の珟実的なものはありたせん。 プレむダヌの船はリゞッドボディを持぀モデルで、各ティックには角速床ず䞊進速床が䞎えられたす。 角速床を取埗するには、䞭心からの倉䜍ベクトルをマりスから取埗し、各ティックでマりスの動きの珟圚のデルタを倉䜍に远加し、ベクトル自䜓に1未満の係数を掛けたす。船の小さな慣性の錯芚で、かなり滑らかな制埡が埗られたす。

䞊進運動の堎合はさらに簡単です。船はロヌカルの「前方」の方向に移動し、W / Sキヌを抌すず速床が埐々に増加たたは枛少したす。

カメラを䜿甚するず、すべおが非垞に簡単になりたした。 額の船にカメラを取り付けるのは悪い考えです。したがっお、カメラず船は接続されおいたせんが、カメラには、船の埌ろから狙っおいる目暙点ず回転角床がありたす。 珟圚のポむントずタヌゲットポむントが補間されるため、「スムヌズトラッキングカメラ」の効果が埗られたす。

速床の感芚を䞎えるために、船の加速で、カメラの芖野はわずかに増加したすが、枛速しながら、それに応じお枛速したす。


あなたは船が䞍快にひき぀る様子を芋るこずができたす。 これは、船の剛䜓蚭定で補間を有効にするこずで解決したした。

隙間を埋める


空の黒いスペヌスでの移動は、どういうわけか面癜くない。 したがっお、次のステップは、宇宙をオブゞェクトで満たすこずでした。
この蚭定では小惑星垯がゲヌムの䌚堎であったため、タスクは非垞に簡単に解決されたした。数癟立方キロメヌトルのスペヌスに、数癟の小惑星がランダムに散らばっおいたした。 ランダム生成のシヌドは事前に保存されおいたため、ベヌスたたはク゚ストアむテムが小惑星内にあるこずを心配する必芁はありたせんでした。


遠くからはこんな感じです。

倧きな「掻気」ずダむナミズムのために、倧きな小惑星に加えお、小さな「スタヌダスト」が远加されたした。 これらのささいなこずは、堎所党䜓ではもはや生成されたせんでしたが、移動する船の呚りに盎接䜜成されたした。

小惑星トリビアゞェネレヌタヌコヌド
public class MiniAsteroids : MonoBehaviour { private Transform tx; private GameObject[] asteroids = new GameObject[155]; public GameObject[] prefabs = new GameObject[2]; public int asteroidsMax = 100; public float asteroidSize = 1; public float asteroidDistance = 10; public float asteroidClipDistance = 1; private float asteroidDistanceSqr; private float asteroidClipDistanceSqr; private ParticleSystem pSystem; private int updateEvery = 5; private int counter = 0; GameObject root; void Start() { root = new GameObject(); root.transform.position = Vector3.zero; root.name = "Small Asteroid Field"; tx = transform; asteroidDistanceSqr = asteroidDistance * asteroidDistance; asteroidClipDistanceSqr = asteroidClipDistance * asteroidClipDistance; pSystem = GetComponent<ParticleSystem>(); } private void CreateStars() { for (int i = 0; i < asteroidsMax; i++) { asteroids[i] = Instantiate(prefabs[Random.Range(0, prefabs.Length - 1)]) as GameObject; asteroids[i].transform.position = Random.insideUnitSphere * asteroidDistance + tx.position; asteroids[i].transform.parent = root.transform; asteroids[i].GetComponent<Rigidbody>().angularVelocity = Random.insideUnitSphere * 2f; } } void Update() { counter++; if (asteroids[0] == null) CreateStars(); if (counter == updateEvery) { counter = 0; for (int i = 0; i < asteroidsMax; i++) { if ((asteroids[i].transform.position - tx.position).sqrMagnitude > asteroidDistanceSqr) { asteroids[i].transform.position = Random.insideUnitSphere.normalized * asteroidDistance + tx.position; asteroids[i].GetComponent<Rigidbody>().velocity = Vector3.zero; } } } } } 


船を歊装したす


メむンキャラクタヌの船は、6぀のサスペンションポむントで歊噚を運ぶ機䌚を䞎えるこずに決めたした重歊装した戊闘機には2぀たたは4぀のポむントは堅すぎたす。 アヌムのアタッチメントポむントはGameObjectsダミヌを䜿甚しお蚭定され、サスペンションのポむント数はハヌドコヌディングされたしたはい、悔い改めたした。 同時に、サスペンションポむントは2぀のタむプに分けられたした-メむンりェポンず補助。 基本的に1぀の違いがありたした-メむンスロットの歊噚はLMBで、远加の歊噚では-スペヌスバヌで有効になりたした。 歊噚は、基本的な機胜ぞのアクセスを提䟛するむンタヌフェヌスを介しお、新しい皮類の歊噚を簡単に远加できるようにするずいう、非垞に限定的な船ずのやり取りを行いたした。 さらに、開発時に、ストアず栌玍庫のむンタヌフェむスでの倖芳を担圓するいく぀かの機胜が远加されたした。

むンタヌフェヌス
 interface IWeapon { void Shoot(Transform target); void Refill(); int GetAmmoNum(); void SetAmmoNum(int n); Vector3 GetJointOffset(); string GetWeaponName(); string GetWeaponTitle(); string GetWeaponDesc(); int GetWeaponPrice(); Vector3 GetGUIRotation(); Vector3 GetGUIScale(); } 



吊り䞋げられた歊噚を持぀船の最初のスクリヌンショットの1぀

合蚈で、5皮類の歊噚が補造されたした。2重砲、レヌザヌ、誘導されおいないミサむル、重いホヌミング魚雷、ホヌミングミサむルです。

タヌゲットが同じ方向に同じ速床で移動するず仮定しお、粟床を高めるためのホヌミングミサむルがリヌドポむントを蚈算したした。 原則ずしお、これはミサむルがかなり高い確率で動いおいるタヌゲットにヒットするのに十分でした。

ガむド付きミサむルスクリプトコヌド
 public class GuidedRocket : MonoBehaviour { public float selfDestructTime = 5f; public float safetyDelay = 0.5f; public float damageRadius = 6f; public int damage = 120; public float acceleration; public float steerCoef = 0.09f; float maxSpeed = 10f; public Collider col; bool armed = false; public Transform smoke; public GameObject explosion; public GameObject target; Vector3 estimatedPosition; Vector3 targetVelocity; Rigidbody targetBody; public Vector3 fwd = -Vector3.up; public Vector3 fixAngle = new Vector3(-90, 0, 0); float startSpeed; bool first = true; Rigidbody body; public LayerMask hitMask; void Start() { Invoke("SelfDestruct", selfDestructTime); Invoke("Arm", safetyDelay); body = GetComponent<Rigidbody>(); } void FixedUpdate() { if (first) { first = false; startSpeed = transform.InverseTransformDirection(GetComponent<Rigidbody>().velocity).magnitude; maxSpeed = startSpeed * 2; if (target != null) { targetBody = target.GetComponent<Rigidbody>(); } } Vector3 fwdDir = transform.TransformDirection(fwd); if (armed) { startSpeed += Time.deltaTime * acceleration; if (target != null) { Vector3 enemyPos = target.transform.position; Vector3 dir = enemyPos - transform.position; if (targetBody != null) { float distance = dir.magnitude; Vector3 tgVel = targetBody.velocity; estimatedPosition = target.transform.position + (distance / startSpeed) * tgVel; //   dir = estimatedPosition - transform.position; } else { } Quaternion targetRotation = Quaternion.LookRotation(dir) * Quaternion.Euler(fixAngle); body.MoveRotation(Quaternion.Lerp(transform.rotation, targetRotation, steerCoef)); } } body.velocity = Vector3.Lerp(body.velocity,fwdDir * startSpeed , 0.5f); } void SelfDestruct() { smoke.parent = null; smoke.gameObject.AddComponent<Autodestruction>().Set(5f); smoke.gameObject.GetComponent<ParticleSystem>().enableEmission = false; explosion.transform.parent = null; explosion.SetActive(true); Destroy(this.gameObject); } void Arm() { armed = true; col.enabled = true; } void OnTriggerEnter(Collider col) { if (armed) { Debug.Log(col.gameObject.name); foreach (Collider c in Physics.OverlapSphere(transform.position, damageRadius)) { if (c.GetComponent<Rigidbody>()) { c.GetComponent<Rigidbody>().AddExplosionForce(20, this.transform.position, damageRadius); c.GetComponent<Rigidbody>().AddTorque(new Vector3(Random.Range(-30f, 30f), Random.Range(-30f, 30f), Random.Range(-30f, 30f))); } if (c.gameObject.GetComponent<IDamageReciever>() != null) { c.gameObject.GetComponent<IDamageReciever>().DoDamage(damage); } } CancelInvoke("SelfDestruct"); SelfDestruct(); } } } 


以䞋は、2皮類の歊噚の動䜜のビデオです。 ビデオには敵の砎壊の効果も瀺されおいたすが、それは非垞に単玔なので、別に説明したせん。





むンタヌフェヌス


むンタヌフェむスに費やした時間は予想倖に非垞に重芁であるこずが刀明し、むンタヌフェむスの開発には少なくずも3日かかりたした。 Unity 4.6に登堎したUIシステムを䜿甚したしたが、私の意芋では、それは非垞に䟿利で、孊ぶのはかなり簡単です。

むンタヌフェむスでの䜜業の䞭で最も難しい郚分はベヌスむンタヌフェむスであり、非垞に倚くの機胜を実装する必芁がありたした。 察話、歊噚の賌入/販売、ホヌルドからのアむテムの販売、修理。 貚物/歊噚アむコンずしお、アむコンを描画する時間が十分になかったため、盎亀投圱のモデルが䜿甚されたした。 アむテムごずに短い説明がたずめられ、プレヌダヌの前に䜕があるかを䌝えたした。


むンタヌフェむスの最初のバヌゞョン、カヌブ、タスクタブなし

埌に、むンタヌフェヌスはグラフィカルに掗緎され圌のためにスプラむトを手䌝っおくれた人のおかげで、私自身は決しおできなかったでしょう、顕著によりきれいできれいになり始めたした。


最終バヌゞョンでは、本質は同じですが、目を楜したせおくれたす。

飛行むンタヌフェヌスがより簡単になりたした。 プレむダヌは実際には圌ずは䞀切察話せず、それ自䜓で圌はかなりミニマルです。 プログレスバヌには、通垞のスプラむトが䜿甚され、Unityを䜿甚しお9぀の郚分にカットされ、非垞に簡単か぀非垞にきれいに氎平に匕き䌞ばされたした。 スコヌプの偎面に湟曲したバヌがあるず、すべおがより耇雑になりたす。 軞の1぀に沿っおスプラむトをストレッチするだけでは機胜したせん。より耇雑な゜リュヌションを䜿甚する必芁がありたす。 単玔なシェヌダヌは、カットオフの高さずいう1぀のパラメヌタヌで蚘述されおいたす。 スクリプトから蚭定され、それに応じお、スプラむトは目的の塗り぀ぶしで描画されたした。

シェヌダヌコヌド
Shader "Custom/CrosshairShader" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_Angle ("Angle (Float)", Float) = 0
_Color ("Tint", Color) = (1.0, 0.6, 0.6, 1.0)
}

SubShader {
Tags{"Queue" = "Transparent" }
Pass {
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag

#include "UnityCG.cginc"

uniform sampler2D _MainTex;
uniform float _Angle;
uniform fixed4 _Color;

float4 frag(v2f_img i) : COLOR
{
float4 result = tex2D(_MainTex, i.uv);
float angle = i.uv.y;

if(angle > _Angle)
{
result.a = 0;
}

return result*_Color;
}
ENDCG
}
}
}


フラむトむンタヌフェヌスのスクリヌンショット


スクリヌンショットは、画面の䞭倮に半分満たされたヘルスむンゞケヌタを瀺しおいたす

盞手


私の意芋では、ゲヌムの匱点の1぀です。 圌らはただ䞀぀の戊術を持っおいたす-プレヌダヌが圌らの芖野に入っおいお、射撃の距離に近づいたら、プレヌダヌの埌に飛ぶこずは、射撃を始めたす。 それにもかかわらず、倚くの堎合、そのような敵でさえ深刻な危険をもたらしたす。

もちろん、䞊蚘の動䜜に加えお、補助機胜もありたした。 たずえば、プレヌダヌの芖界を倱った圌らは、圌を芋た最埌のポむントたで飛んで、そこで圌を芋぀けられなかった、ランダムにさたよい始めた、たたは開始ポむントに戻った。 それでも、圌らは小惑星ずの衝突を時々避けたが、それは圌らがあたりに速く飛ばなかった堎合だけだ。 敵のAI甚の本栌的なステヌトマシンはそのようには実装されおいたせんでした。AIスクリプトは0.1秒ごずにパスを開始し、次の0.1秒で敵が䜕をするかを決定したした。 このため、倚かれ少なかれ蚱容できる動䜜を実珟するために、AIの状態を蚘述する倚くの远加倉数を開始する必芁がありたした。


メむンボスは完党に無防備であり、圌の膚倧な数の手䞋だけに頌っおいたした。

ク゚スト


それ以前は、ク゚ストシステムを実行したこずがなかったため、どこから始めればよいのかわかりたせんでした。 しかし、掚論する時間やレッスンを探す時間はありたせんでした。行動する必芁がありたした。2週目が続いおいたからです その結果、ハヌドコヌド化されたク゚ストのリストを備えた非垞にsystemいシステムが生たれたした新しいク゚ストを远加するには、メむンク゚ストスクリプトの倉数にその名前を曞き、ク゚ストの数を1぀増やし、ク゚ストが参照するベヌスを指定する必芁がありたす、ダむアログの固定数の回答オプション3ピヌス、およびレヌキゞャンプのその他の兆候がありたす。

ダむアログはxmlに保存されたした。線集のために、Unityの同じ堎所で簡単な゚ディタヌも䜜成されたした。


゚ディタヌはおそらくク゚ストシステムの最も優れた郚分です。

ク゚スト自䜓はプレハブによっお䜜成され、プレハブはク゚ストの起動時にむンスタンス化され、賞を受け取った埌に削陀されたした。 曲がっおいたすが、うたくいきたした。 ク゚ストシステム、ダむアログの䜜成、およびク゚スト自䜓はさらに3日間かかりたした。 締め切りは間近に迫っおいたした。

その他のささいなこず


ここでは、別のセクションに倀しないさたざたなチップをリストしたいず思いたすが、それでもそれに぀いおお話ししたいず思いたす。

倚分、ハむパヌゞャンピングの効果から始めたしょう。 どのように芋えるか、以䞋を芋るこずができたす。



非垞に簡単に実装されたす。 最初にサりンドを開始し、カメラを振っお、メむンモデルの䞊に同じ船のわずかに拡倧したモデルを衚瀺したすが、「゚ネルギヌフィヌルド」のテクスチャを䜿甚しお、アニメヌションカヌブでアニメヌション化し、ゞャンプの前にパヌティクルフラッシュシステムを起動しおメむンモデルを非衚瀺にしたす。 「䜎予算」効果のためにそれがうたくいったように思えたす。

たた、保存システムに぀いお少し説明したいず思いたす。 奇劙なこずに、圌女はゲヌムに参加しおいたす。 プレヌダヌの名前を含むxmlファむルはゲヌムフォルダヌに保存され、プレヌダヌの名前自䜓はPlayerPrefsレゞストリ内に保存されたす。 理論的には、メむンメニュヌでプレヌダヌの名前を倉曎するこずで、耇数の保存を䜿甚するこずもできたす。 ク゚ストが完了するたびに、保存は自動的に行われたす。

非垞に簡単に実装されたすSaveInfoクラスが䜜成され、ゲヌムの必芁なすべおの状態パラメヌタヌが保存されたす。このクラスは、暙準Cツヌルを䜿甚しおデヌタをxmlファむルにシリアル化/非シリアル化する2぀のメ゜ッドLoadおよびSaveを実装したす

ロヌドしお保存
 public void Save(string path) { var serializer = new XmlSerializer(typeof(SaveInfo)); using (var stream = new FileStream(path, FileMode.Create)) { serializer.Serialize(stream, this); stream.Close(); } } public static SaveInfo Load(string path) { var serializer = new XmlSerializer(typeof(SaveInfo)); using (var stream = new FileStream(path, FileMode.Open)) { return serializer.Deserialize(stream) as SaveInfo; } } 


それだけです。他に䜕もする必芁はありたせん。このクラスのフィヌルドを解析するだけです。

ファむルを保存
 <?xml version="1.0" encoding="windows-1251"?> <SaveInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <name>Mingebag</name> <money>150</money> <health>460</health> <maxHealth>500</maxHealth> <maxcargo>2500</maxcargo> <maxSpeed>25</maxSpeed> <acceleration>3</acceleration> <yawPitchFactor>1.99</yawPitchFactor> <rollFactor>1.98</rollFactor> <wS1Name>Machinegun</wS1Name> <wS1Num>0</wS1Num> <wS2Name>Machinegun</wS2Name> <wS2Num>0</wS2Num> <auxName> <string>GuidedLauncher</string> <string>NursLauncher</string> <string>NursLauncher</string> <string>GuidedLauncher</string> </auxName> <auxNum> <int>6</int> <int>18</int> <int>18</int> <int>9</int> </auxNum> <spawnInNextScene>false</spawnInNextScene> <spawnPositionIndex>0</spawnPositionIndex> <spawned>true</spawned> <hasActiveQuest>false</hasActiveQuest> <base1QuestNum>0</base1QuestNum> <base2QuestNum>0</base2QuestNum> <InventoryItems> <Item> <name>Equipment3</name> <title> </title> <desc>  ,   .</desc> <weight>300</weight> <quantity>1</quantity> <price>100</price> </Item> <Item> <name>Equipment2</name> <title> </title> <desc>  .    </desc> <weight>150</weight> <quantity>1</quantity> <price>100</price> </Item> <Item> <name>Debris</name> <title> </title> <desc>  .    </desc> <weight>50</weight> <quantity>1</quantity> <price>10</price> </Item> </InventoryItems> </SaveInfo> 


したがっお、ゲヌムを進めるのが面倒な堎合は、保存しお進行を加速したり、歊噚をより匷力にしたりするこずができたす。

たた、ゲヌムのグラフィックコンテンツの開発を手䌝っおくれた開発プロセスのすぐれた善良な人々にも感謝したいず思いたす。 その量を考えるず数十のモデルのみ、私はそれを時間通りに捕たえるこずができるずは思わず、品質に぀いお話す必芁はありたせん。 その結果、ゲヌム内のほずんどすべおのグラフィックス2぀の背景ずスカむボックスを陀くは、このゲヌム専甚に䜜成されたした。

たずめ


ゲヌムの䜜業が終了しおから半幎以䞊が経過しおおり、圚庫を確認する時が来たした。

私はこのゲヌムで最優秀賞を獲埗したせんでした。どうやらピクセルアヌトアドベンチャヌのトレンドに参加できなかったようです。 しかし、ゲヌムの䜜業䞭に非垞に倚くの貎重な経隓ずスキルが埗られ、远い越されたレヌキからのバンプは、いく぀かのこずは䟡倀がないこずを長い間思い出させたす。

結論


もちろん、私の結論の倚くは明癜に思えるかもしれたせんが、時には詊しおみないず理解できないでしょう。 たずえば、プロゞェクトをできるだけ耇雑にしたいずいう欲求は、初心者の開発者が犯す最も䞀般的な間違いの1぀です。 私もこの問題を回避できたせんでした。

最埌に、ゲヌムのゲヌムプレむビデオを玹介したす。 その䞊で、最終的に䜕が起こったかを倧たかに評䟡できたす。



この蚘事が䜕らかの圢であなたの圹に立぀こずを願っおいたす。少なくずも、別の小さなゲヌムの開発の歎史を知るこずは興味深いものでした。

ビルドぞのリンク
yadi.sk/d/j-v8WoyCiaNuQ

GitHubリポゞトリぞのリンクコンテストがほずんど修正されなかった埌の生のコヌド、およびすべおが急いで曞かれたため、真珠はそこにいっぱいです
github.com/TxN/TWG6-Spacesim

Source: https://habr.com/ru/post/J279231/


All Articles