void Start() { gridPos.x = FrogWorld.numGridsX / 2; gridPos.z = maxGridZ; // add death state eventDeath += () => { mesh.material.SetColor("_Color", Color.white * 0.3f); transform.DOKill(true); //transform.DOPunchRotation(Vector3.one * 15.0f, 0.4f, 10); transform.DORotateQuaternion(Quaternion.Euler(90.0f, 0.0f, 0.0f) * transform.rotation, 0.2f).SetEase(Ease.OutBack); var newScale = transform.localScale; newScale.Scale(new Vector3(0.75f, 0.75f, 0.75f)); transform.DOScale(newScale, 0.2f).SetEase(Ease.OutBack); this.StopAndNullify(ref threadMoving); }; threadMoving = StartCoroutine(HandleMovement()); transform.localScale = Vector3.one * FrogWorld.gridSize; transform.position = FrogWorld.GridToWorldPos(gridPos); }
/*void OnTriggerEnter2D(Collider2D collisionObj) * { * if (collisionObj.gameObject.layer == LayerMask.NameToLayer("Zone")) * { * var collisionGameObj = collisionObj.gameObject; * * // doesn't touch? * if (!touchedZones.Contains(collisionGameObj)) * { * var zone = collisionGameObj.GetComponent<Zone>(); * * if (zone.eventTouched != null) * zone.eventTouched(); * * lifeSpan = Mathf.Min(lifeSpan + lifeSpanEat, lifeSpanMax); * * touchedZones.Add(collisionGameObj); * fitness += 1.0f; * } * } * } * * void OnCollisionEnter2D(Collision2D collisionObj) * { * if (collisionObj.gameObject.layer == LayerMask.NameToLayer("Obstacle")) * { * TriggerDeath(); * } * }*/ IEnumerator HandleMovement() { FrogWorld frogWorld = FrogWorld.Instance; float gridSize = FrogWorld.gridSize; while (true) { UpdateNeuralNetOutput(); GridPos gridDelta = new GridPos(0, 0); // wait for input while (true) { if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow)) { --gridDelta.x; } else if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow)) { ++gridDelta.x; } else if (Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.DownArrow)) { --gridDelta.z; } else if (Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow)) { ++gridDelta.z; } /*if (Random.Range(0,2) == 0) * gridDelta.x = Random.Range(0, 3) - 1; * else * gridDelta.z = Random.Range(0, 3) - 1;*/ // neural network input var maxIndex = -1; var maxVal = -99.0f; for (int i = 0; i < 4; ++i) { var val = neuralNet.GetOutputData(i); if (Mathf.Abs(val) > maxVal) { maxVal = Mathf.Abs(val); maxIndex = i; } } if (maxIndex == 0) { gridDelta.x += 1; } if (maxIndex == 1) { gridDelta.x -= 1; } if (maxIndex == 2) { gridDelta.z -= 1; } if (maxIndex == 3) { gridDelta.z += 1; } if (gridDelta.x != 0 || gridDelta.z != 0) { break; } yield return(null); } var simTimeScale = FrogSimulation.simTimeScale; // new grid pos GridPos newGridPos = gridPos + gridDelta; Vector3 newPos = new Vector3(newGridPos.x * gridSize, gridSize * 0.5f, newGridPos.z * gridSize); // turn var turnAngle = Mathf.Rad2Deg * Mathf.Atan2(-gridDelta.z, gridDelta.x) + 90f; transform.DORotate(new Vector3(0.0f, turnAngle, 0.0f), 0.1f * simTimeScale).SetEase(Ease.OutBack); // hits wall if (frogWorld.HasObstacle(newGridPos)) { --numTurnsLeft; var partPos = Vector3.Lerp(transform.position, newPos, 0.25f); yield return(transform.DOMove(partPos, 0.05f * simTimeScale).SetLoops(2, LoopType.Yoyo).WaitForCompletion()); } else // move to empty spot { particles.Emit(1); // move there yield return(transform.DOMove(newPos, 0.1f * simTimeScale).SetEase(Ease.OutBack).WaitForCompletion()); // moving forward if (newGridPos.z > maxGridZ) { numTurnsLeft = Mathf.Max(numTurnsLeft, numTurnsReplenishedMoveForward); maxGridZ = newGridPos.z; fitness += 1.0f; // Finished! if (newGridPos.z >= FrogWorld.numGridsZ - 1) { yield return(transform.DOMove(newPos + Vector3.up * gridSize * 0.5f, 0.2f).SetLoops(12, LoopType.Yoyo).WaitForCompletion()); TriggerDeath(); } } else // not moving forwad { --numTurnsLeft; } gridPos = newGridPos; } // no more turns left if (numTurnsLeft < 0) { TriggerDeath(); } yield return(null); } }