ç¥ç¶ã¯ã«ããæ€ããŸãã...ãããŠè§Šæã¯ããããcãåºããŸãããUPDïŒçŽ³å£«ã®
çãã ãéäŒããŠãã ãããèšäºã®äœãæªãã®ããããã誰ããæãããã®ãã ãããŠãåŸãåãããšãã«ã«ãã«é£ã³èŸŒã¿ãŸããããäœãä¿®æ£ãã¹ããã¯æ確ã§ã¯ãããŸããã
欲ã®ããã§ã¯ãªãããç§ã¯...UPD 2ïŒèŠå
ãå¿ããŸãã...ãããã°ã¢ãŒãã§ãUnityEditorã¯ã³ã³ãœãŒã«ã«åå
æ°ã®ç¡å¹ãªå€ã«é¢ããäœçŸãã®ã¡ãã»ãŒãžã衚瀺ããŸãïŒæããã«æ£èŠåãããŠããŸããïŒã ãã®ããããããã°ã®ããæç¹ããéå§ããŠãé床ãäœäžãå§ããŸãã ç§ã®é害ããã°ãUnityãªãªãŒã¹ã®æ©èœã§ãããã©ããã¯ãŸã ããããŸããã Handsã¯ãUnity3Dãã©ãŒã©ã ã«è³ªåãæçš¿ããæ¹æ³ã¯äžåãããŸããã
ã¯ããã«
FrozmatGamesæ°
ã®èšäºã èªã㧠ãç§ã¯ãã®èšäºãæ¥ãã§
é§ãç«ãŠãŸããããã®èšäºã§ã¯ãéºäŒåŠãããŒãã«ããã²ãŒã ã®ãããã¿ã€ãã®å®è£
ã«ã€ããŠèª¬æããŸãã ããã¹ãã®æ¹¿æ°ã®å¯èœæ§ã«ã€ããŠäºåã«è¬çœªããŸãã ãã³ãŒãã³ã°ãã®æéã足ããŸããã ã¹ã©ãã®ã³ã°ããã®ä»ã®ããã¹ãã®æ¬ é¥ã«ã€ããŠã®æãã®habrapochtaã§éã£ãŠãã ãã-ç§ã¯ãã¹ãŠãä¿®æ£ããããšããŸãã
ãã®èšäºã§ã¯ãäœæããããã¢ã®ã³ã³ã»ãããææ©çæé·ã®ã·ãã¥ã¬ãŒã·ã§ã³ã§ç°¡åã«èª¬æããããšããŸãã æåã«ããã¢ãäœæãããšããã¢ã€ãã¢ã«ã€ããŠèª¬æããŸãã 次ã«ã䜿çšãå§ããããŒã«ãšæçµçã«äœ¿çšããããŒã«ã«ã€ããŠèª¬æããŸãã ããã§ã¯ãå®è£
ã®ããã€ãã®ãã€ã³ãã®èª¬æããã¢ã³ã¹ãã¬ãŒã·ã§ã³ãããã«å®è£
ãããããšã®ãªã¹ãã§çµãããŸãã
ãã€ãã®ããã«ãã³ãŒãã¯Githubã«æçš¿ãããŠããŸãã
ã²ãŒã ã®ã¢ã€ãã¢ãšãããã¿ã€ãïŒ1
ç§ã®ã€ã³ã¹ãã¬ãŒã·ã§ã³ã®äž»ãªæ
å ±æºã¯ãStrugatskyå
åŒã®äžçïŒA.ãBããããã³J.ïŒãšããã«é¢ããããã€ãã®èšäºã§ãïŒä»¥äžã®ãªã¹ããåç
§ïŒã
åºæ¬çãªèãæ¹ã¯ããã¹ãŠãŸãã¯ã»ãšãã©ãã¹ãŠãçåœã§æºããããæ§ç¯ããããçµã¿ç«ãŠãããã補é ããããçãŸããçºå±ããæé·ããã²ãŒã ã®äžçã§ãã å
šäœãšããŠããã©ãªã¢ãšèåã®æ··åç©ã ããã¯ãã²ãŒã ã®ã¢ã€ãã¢ã«ã€ããŠç°¡åã«èª¬æããŸãã ãŸã 詳ããã¯èª¬æããŸããããã®åã«ãèããæŽçããå¿
èŠããããŸãã
ãããã¿ã€ãã®å®è£
ããå§ããããšã«ããŸããããã®ãããã¿ã€ãã§ã¯ãç¹å®ã®æœè±¡çãªæ€ç©ã®èªçãšçºå±ã芳å¯ããããšãå¯èœã«ãªããŸãïŒèšäºã®ã¿ã€ãã«ã®ã¯ãŒãã³ã°ã¿ã€ãã«ïŒã äžã®å³ã¯ãèæ¡ããããããã¿ã€ãã®ã¹ã±ããã§ãã

ãã®ã¹ã±ããã¯ããªããžã§ã¯ãã®éçºã®åæ段éã瀺ããŠããŸãã ãã®æ®µéã§ãããããã€ãªã骚ãšã²ãã¯æ žãããæé·ãããŸãã ããŒã³ãšã¹ããªã³ã°ã¯åå²ããããšããã³ã¢ããæ°ãããã®ãè¿œå ããããšãã§ããŸãã æ§é ã®äžéšã倧ãããªããšããžãªã¡ããªãšç©ççç¹æ§ãå€æŽã§ããŸãã

åå²ãšæ¿å
¥ã¯ãã
ç¥çµé²åã®ããããžãŒã®é²åãã§è©³ãã説æãããŠãã2ã€ã®æäœã§ãã ãããã¯éºäŒåã§æå·åã§ãããããå°æ¥çã«ã¯äžçã®é²åã«éºäŒçã¢ã«ãŽãªãºã ã䜿çšã§ããŸãã
Physics2D.Net + WPF Render vs Unity3D 4.3.0
åœåããããã¿ã€ãã®å®è£
ã¯Physics2D.Netã䜿çšããŠæ±ºå®ãããŸããã 圌ãšä»äºãããã®ã¯ç°¡åãªããã§ãïŒ
wikiã®è人ã«é¢ããç°¡åãªãã¥ãŒããªã¢ã«ãèªãããšãã§ããŸãïŒïŒ
PhysicsEngine engine = new PhysicsEngine(); engine.BroadPhase = new Physics2DDotNet.Detectors.SelectiveSweepDetector(); engine.Solver = new Physics2DDotNet.Solvers.SequentialImpulsesSolver();
ã¿ã€ããŒãªããžã§ã¯ãïŒ
PhysicsTimer ïŒã䜿çšããŠã·ãã¥ã¬ãŒã·ã§ã³ãéå§ããã³åæ¢ããŸãã
PhysicsTimer timer = new PhysicsTimer(engine.Update, .01f); timer.IsRunning = true;
ãããããã¡ããæ©äŒã¯ååã§ã¯ãããŸããã ããã«ãã·ãŒã³ã®ã¬ã³ããªã³ã°ãåé¡ã§ããã WriteableBitmapã§ã®ã¬ã³ããªã³ã°ãæãç°¡åãªãœãªã¥ãŒã·ã§ã³ãšããŠäœ¿çšãããŸããïŒ
ãªããžããªå
ã®ã³ãŒã
ãåç
§ïŒã åŸã§ãã®ã¢ãããŒããæŸæ£ããŸãã ã¬ã³ããªã³ã°ãããçç£çãªãã®ã«çœ®ãæããã®ã¯é£ãããšæããŸããã ãã£ãšæ©èœçãªãã®ãããã«åŠã¶æ¹ãè¯ããšç§ã¯æ±ºããŸããã Physics2D.Netã«ã€ããŠèªãããšã«èå³ããã人ã¯ãã³ã¡ã³ãã®è³Œèªãäžæ¢ããŠãã ããããã®æéãèŠã€ããããšããŸãã
ãã€ãã£ã2Dã¢ãŒããå®è£
ããUnity3D 4.3.0ãªãªãŒã¹ã«é¢ããèšäºã®åŸããã¢ãå®è£
ããããšã«ããŸããã Unity3Dãããžã§ã¯ãã¯ãã³ãŒããæŽçããããã®ã³ã³ããŒãã³ãã¢ãããŒãã®å€§èŠæš¡ãªäœ¿çšã§ããç¥ãããŠããOOPã¢ãŒããã¯ãã£ãšã¯ç°ãªããŸãã ãã®ãããPhysics2Dãåãããã©ã³ãã®ã³ãŒãã¯ã䜿çšããã®ã§ã¯ãªãããŒãããå®è£
ãéå§ããããšã«ããŸããã
ç§ã®ã³ã³ã»ããã®åºç€ãšããŠãç§ã¯2Dãã¢ãããžã§ã¯ãïŒ
ããã¯ãã¡ã ïŒãåããŸããã ã²ãŒã ãªããžã§ã¯ããšåäœã·ããªãªã®äž»èŠéšåã®ã¹ãã©ã€ããäœæããŸããã ãŸããããŸããŸãªãã«ããŒå®è£
ããããžã§ã¯ãã«è¿œå ãããŸããã
圌ã¯ãUnity3Dã®åŸæ¥ã®OOPã¢ãããŒãã§ã¯é£ãããšæã£ãŠããŸããã è¡åã·ããªãªã®ããªã¢ãŒãã£ãºã ã¯æ©èœããŸããã ããããäžè¬çã«ãåŸæ¥ã®OOPã«ã¯ããã»ã©å€ãã®åé¡ã¯ãããŸããã§ãã...ãããããããŸã§ã®ãšããã ãœãªã¥ãŒã·ã§ã³ã䜿çšãããšãã¯ãMono Developã ãã§ãªãVisual Studio 2012ã䜿çšããŸãã ãã®äžã®CïŒãšãã£ã¿ãŒã¯ãããè¯ãå®å®ããŠããŸãã Faced MonoãªãŒãã€ã³ãã³ããã³ãŒãã®äžéšã®ãã©ãã°ã¢ã³ãããããããã©ã±ããã®èªåã¯ããŒãºããã®ä»ã®äºçŽ°ãªåé¡ãéçºããŸãã ããããç§ã¯ãŸã VSãéããŠããã¥ãŒããæ¹æ³ãåŠãã§ããŸããã ãšããã§ãMono Developã«ã¯ãããã°ã«é¢ããåé¡ããããŸãã äœããã®çç±ã§ã
enumãå«ãåå空éã¯ãããã°ã§ã¢ã³ããŒããããŸããããã¯ãã²ãŒã ãªããžã§ã¯ãã®ã¿ã€ãããããã°ã§è¡šç€ºãããªããããæååå€æ°ã§è€è£œããå¿
èŠãããããã§ãã ãã¶ããããªãã¯ãç¥ããªãããå¥ã®åå空éã«åæãããç¡é§ãªåæããããŸããã
å®è£
çŸåšå®è£
ãããŠãããã®ïŒ
- ã³ã¢ïŒã³ã¢ïŒãããŒãïŒããŒãïŒãããã³ããŒã³ïŒéªšïŒã®3çš®é¡ã®ãã¬ãããè¿œå ãããŸãã
- ããŒããšããŒã³ã«ã¯ããã€ãã®ã¿ã€ãããããã³ã¢ã¯åãã¿ã€ãã§ã
- DNAãããã³ãã®çµæã®éºäŒåã®èªã¿èŸŒã¿ããã³ãŒããè€è£œãå®è£
ããŸããã ãªããžããªå
ã®ã¹ã¯ãªããSeedãDnaProcessorãGeneProcessorãåç
§ããŠãã ãã
- 埩å·åãããéºäŒåã¯ãé©çšå¯èœæ¡ä»¶ãæºãããšãã«ã²ãŒã ãªããžã§ã¯ãã®çŸåšã®éšåã«é©çšãããŸã
- éºäŒåã®é©çšå¯èœæ§ã«é¢ãã以äžã®æ¡ä»¶ãå®è£
ãããŠããŸãããªããžã§ã¯ãã®èŠçŽ ã®ããªãŒå
ã®çŸåšã®äœçœ®ïŒÂ±ã©ã³ãã 蚱容å€ïŒã 芪èŠçŽ ã®ãµãã¿ã€ãã éºäŒå掻æ§åæéã
- 骚ããã³ããŒââãéºäŒåã«ã€ããŠãåèŠçŽ ã®è¿œå ãå®è£
ãããŸãã
- æé·ã®ããŸããŸãªæ®µéãå®è£
ããã¹ã¯ãªããã¯ãçŸåšã®GameObjectã®ã³ã³ããŒãã³ãã«ãããŒããã£ã¹ãã¡ãã»ãŒãžïŒGameObject.SendMessageïŒãéä¿¡ããããšã§äºãã«éä¿¡ããŸãã
- ããŒããè¿œå ãããšãã®ç°¡åãªã¢ãã¡ãŒã·ã§ã³ãå®è£
ããŸããã
- éºäŒåïŒGenesManagerïŒãšãªãœãŒã¹å
ã®ãã¬ããïŒPrefabsManagerïŒãæäœããããã®2ã€ã®ã·ã³ã°ã«ãã³ãã«ããŒãå®è£
ãããŠããŸãã
ãã¢ã§ããå°ã詳现ãªã©ã€ããµã€ã¯ã«ã
æ œå¹ããããªããžã§ã¯ãã®ã«ãŒãã¯ã³ã¢ïŒãã¬ããã³ã¢ïŒã§ãã ãã®ãªããžã§ã¯ãã«ã¯ããdna.txtãã®ãªãœãŒã¹ããããŒãããã·ãŒãã¹ã¯ãªããããããŸãã
using UnityEngine; using System.Collections; using Fukami.Helpers; public class Seed : MonoBehaviour { public string Dna; void Start(){ var dnaAsset = Resources.Load<TextAsset>("dna"); Dna = dnaAsset.text.Replace("\r\n","*"); } void OnSeedDnaStringRequested (Wrap<string> dna) { dna.Value = Dna; dna.ValueSource = "Seed"; } }
ãã®ãã¡ã€ã«ã«ã¯ãå®å
šãªã«ãã®DNAãå«ãŸããŠããŸãã
// nodeã[Node type]ã[Bone Type]ã[Base depth]ã[Depth depth]ã[Grow Time]
ããŒãã1,0,0,0,07A
ããŒãã1,0,0,0,080
ããŒãã2,0,0,0,100
骚ã1,0,4,2,190
骚ã1,0,4,2,15E
ããŒãã3ã0ã3ã2ã96
骚ã1,0,0,5ãC8
骚ã1,0,2,1ãFA
骚ã1,0,3,1,12C
ããŒãã2,0,3,2ãFa
ããŒãã1,0,7,3,80
骚ã1,0,8,2,128
ãŸããDnaProcessorã¹ã¯ãªãããã«ãŒãã«ã«æ¥ç¶ãããŠãããæåã«çŸåšã®èŠçŽ ã«èŠªããããã©ããããã§ãã¯ãããŸãã
void Start() { _age = 0.0f; var dna = new Wrap<string>(); if (gameObject.transform.parent != null) { var gen = new Wrap<int>(); gameObject.transform.parent.SendMessage("OnDnaGenRequested", gen); _generation = gen.IsSet ? gen.Value + 1 : 0; gameObject.transform.parent.SendMessage("OnDnaStringRequested", dna); } else { SendMessage("OnSeedDnaStringRequested", dna); } if (dna.IsSet) { DnaString = dna.Value; } }
芪ããªãå ŽåãDnaProcessorã¯ãã·ãŒãã¹ã¯ãªããããDNAãèŠæ±ãããOnSeedDnaStringRequestedãã¡ãã»ãŒãžãéä¿¡ããŸãã ããã§ãªãå Žåã芪èŠçŽ ã®åãDnaProcessorããDNAãåä¿¡ããããã«ãã¡ãã»ãŒãžãOnDnaStringRequestedããéä¿¡ãããŸãã ãŸããDnaProcessorã¯ããã®å€ãéºäŒåã«æž¡ãããã«ãããªãŒã®çŸåšã®äœçœ®ïŒæ·±ããäžä»£ïŒã芪ã«èŠæ±ããŸãã
éºäŒåã®ã©ã€ããµã€ã¯ã«ã¯ãGeneProcessorã¹ã¯ãªããã«ãã£ãŠå¶åŸ¡ãããŸãã ãã®ã¹ã¯ãªããã¯éåžžã«åçŽã§ãã¢ã¯ãã£ããŒã·ã§ã³æéãã«ãŠã³ãããŠããããOnApplyGeneããšããã¡ãã»ãŒãžãéä¿¡ããŸãã
void Update () { if (Gene != null) { _age += Time.deltaTime; } if (_age >= Gene.GrowTime) { enabled = false; SendMessage("OnApplyGene", Gene); return; } }
ãã®ã¡ãã»ãŒãžã¯ããBonesApplicantãïŒçŸåšã®èŠçŽ ãããŒãã®å ŽåïŒããŸãã¯ããŒã³ã®å ŽåãNodesApplicantãã®ããããã§åãå
¥ããããŸãã OnApplyGeneã¡ãã»ãŒãžãã³ãã©ãŒã®ãããã®ã¹ã¯ãªããã¯ã©ã¡ãããéºäŒåã®é©çšæ§ã®æ¡ä»¶ãšã«ãŒã«ããã§ãã¯ããŸãã
bool GetIsApplicable(GeneData gene) { // Part Type check if (gene.GeneType != "node" && gene.GeneType != "stats") { return false; } // Subtype check if (gene.ApplicantSubtype != 0 && gene.ApplicantSubtype != Subtype) { return false; } // Generation check var gen = Generation; if (gen != gene.BaseDepth) { var actDistance = Mathf.Abs(gen - gene.BaseDepth); if (UnityEngine.Random.Range(0f, 1f) < actDistance / (gene.DepthTolerance + 1)) { return false; } } return true; }
void OnApplyGene(GeneData gene) { if (!GetIsApplicable(gene)) return; switch (gene.GeneType.ToLower()) { case "bone": AddBone(gene); break; case "joint": AddJoint(gene); break; case "stats": AddStats(gene); break; default: break; } }
ãã¹ãŠãæ£åžžã§ããã空ãã¹ãããïŒ
ChildSlotãªã¹ã ïŒãããå ŽåãéºäŒåã®åãäœæãããŸãã
private void AddBone(GeneData gene) { var slot = Slots.FirstOrDefault(s => !s.IsOccupied); if (slot == null) { return; } slot.IsOccupied = true; var bonePrefab = PrefabsManager.Instance.LoadPrefab(string.Format("{0}{1}", gene.GeneType, gene.Subtype)); var newBody = (GameObject)Instantiate(bonePrefab, gameObject.transform.position, gameObject.transform.rotation * Quaternion.AngleAxis(slot.Angle, Vector3.forward)); newBody.transform.parent = gameObject.transform; newBody.SetActive(true); //var slide = newBody.AddComponent<SliderJoint2D>(); var slide = newBody.AddComponent<HingeJoint2D>(); slide.connectedBody = gameObject.GetComponent<Rigidbody2D>(); slide.connectedAnchor = new Vector2(slot.X, slot.Y); //slide.limits = new JointTranslationLimits2D { min = -0.1f, max = 0.1f }; slide.limits = new JointAngleLimits2D { min = -1.0f, max = 1.0f }; slide.useLimits = true; gameObject.SendMessage("OnChildAdded", newBody, SendMessageOptions.DontRequireReceiver); } bool GetIsApplicable(GeneData gene) { // Part Type check if (gene.GeneType != "bone" && gene.GeneType != "stats" && gene.GeneType != "joint") { return false; } // Subtype check if (gene.ApplicantSubtype != 0 && gene.ApplicantSubtype != Subtype) { return false; } // Generation check var gen = Generation; if (gen != gene.BaseDepth) { var actDistance = Mathf.Abs(gen - gene.BaseDepth); if (UnityEngine.Random.Range(0f, 1f) < actDistance / (gene.DepthTolerance + 1)) { return false; } } return true; }
private void AddNode(GeneData gene) { var slot = Slots.FirstOrDefault(s => !s.IsOccupied); if (slot == null) return; slot.IsOccupied = true; var nodePrefab = PrefabsManager.Instance.LoadPrefab(string.Format("{0}{1}", gene.GeneType, gene.Subtype)); var newBody = (GameObject)Instantiate(nodePrefab, gameObject.transform.position, Quaternion.FromToRotation(Vector3.right, Vector3.up) * //Quaternion.AngleAxis(Random.Range(-slot.Angle, slot.Angle), Vector3.forward)); Quaternion.AngleAxis(slot.Angle, Vector3.forward)); newBody.transform.parent = gameObject.transform; newBody.SetActive(true); var hinge = newBody.AddComponent<HingeJoint2D>(); hinge.connectedBody = gameObject.GetComponent<Rigidbody2D>(); hinge.connectedAnchor = new Vector2(slot.X, slot.Y); hinge.limits = new JointAngleLimits2D { min = -1.0f, max = 1.0f }; hinge.useLimits = true; newBody.AddComponent<HingeSmoothPos>(); gameObject.SendMessage("OnChildAdded", newBody, SendMessageOptions.DontRequireReceiver); }
åèŠçŽ ã¯ãPrefabsManagerãä»ããŠã€ã³ã¹ã¿ã³ã¹åãããŸããPrefabsManagerã¯ãã¹ããªã³ã°ã¿ã€ãïŒ
boneãŸãã¯
node ïŒããã³ãã¬ãããµãã¿ã€ãã®æ¥å°ŸèŸã«ãã£ãŠãã¬ãããéžæã
ãŸã ã ããšãã°ããnode1ãããnode2ããªã©ã«ãªããŸãã DieIfNoChildrenã¹ã¯ãªããã¯ããŒãã«è¿œå ã§ã¢ã¿ãããããŸããããã¯ãäžå®ã®æéãçµéããŠãåãããŒãã«ã¢ã¿ãããããªãå ŽåãããŒããåçŽã«ç Žæ£ããŸãã
å€ãã®ãã€ã³ãã«ã€ããŠãåå¥ã«äŒããããšããããŸãã 質åãã-ã³ã¡ã³ãã§è©³çŽ°ã«åçããããå¥ã®æçš¿ãããããšããããŸãã ãããŸã§ã®éãããè¯ããã¢ã¢ãã¡ãŒã·ã§ã³ãã玹ä»ããŸãã
ãªããžããªã«ã¢ã»ã³ãã«ãããEXE
ãããŠã³ããŒãã§ã
ãŸã ã
YouTubeã«éä¿¡ããããã«ç»é¢ãããããªããã£ããã£ãã䟿å©ã§ç¡æã®æ¹æ³ãplizã«æããŠããã人ãããŸã次ã¯äœã§ãã
次ã«ãDNAã䜿ã£ãŠãå€å°ãªããšãçŸããã·ãã¥ã¬ãŒã·ã§ã³ãååŸããããšæããŸãã ãžã§ã€ã³ãã®éºäŒåïŒãžã§ã€ã³ãã2ã€ã®ããŒããæ¥ç¶ããèŠçŽ ïŒã®åŠçãããã³ç¹æ§ã®ä¿®é£ŸåïŒçµ±èšã質éããã®ä»ã®ç©çä¿æ°ãããããã€ã³ããªã©ïŒã®åŠçãå®è£
ããå¿
èŠããããŸãã 次ã«å®è£
ããäºå®ã®èŠçŽ ã¯ã骚ãšããŒãã®è¿œå èŠçŽ ïŒä¿è·ã«ããŒãäžéšã®æ»æèŠçŽ ãªã©ïŒãããã³éªšãç Žå£ããããããŒã¿ã«ã«çœ®ãæããæ©èœã§ãã æåŸã«ããã¢ã©ãã©ãªã¢ãã«ã¿ãããŠã¹ã®ãããªãã®ããŸãã¯ãã³ã«ãŒã®ãããªãã®ãæã«å
¥ãããã§ãã
ïŒ ãæž
èŽããããšãããããŸããïŒ