public int Compare(GameObject xObj, GameObject yObj) { if (xObj != null && yObj != null) { AIUnit x = xObj.GetComponent <AIUnit>(); AIUnit y = yObj.GetComponent <AIUnit>(); if (x != null && y != null) { float first = Vector3.Distance(this.transform.position, x.transform.position); float second = Vector3.Distance(this.transform.position, y.transform.position); if (first > second) { return(-1); } else if (first == second || first.Equals(second) || Mathf.Abs(first - second) < float.Epsilon) { return(0); } else { return(1); } } } return(0); }
public void OnTriggerExit(Collider other) { AIUnit attackRange = other.GetComponentInParent <AIUnit>(); if (attackRange != null && attackRange.teamFaction != this.teamFaction && this.enemies.Contains(attackRange.gameObject)) { this.enemies.Remove(attackRange.gameObject); } else { GameUnit unit = other.GetComponent <GameUnit>(); if (unit != null && unit.teamFaction != this.teamFaction && this.enemies.Contains(unit.gameObject)) { this.enemies.Remove(unit.gameObject); } } }
//------------------------------------ private GameObject SplitUnit(AIUnit original) { original.SetSplitFlag(); if (original.currentState == State.Split) { GameObject obj = MonoBehaviour.Instantiate(this.AIUnitPrefab) as GameObject; if (obj != null) { obj.transform.SetParent(original.transform.parent); obj.transform.position = original.transform.position; AIUnit unit = obj.GetComponent <AIUnit>(); if (unit != null) { unit.Copy(original); } } return(obj); } return(null); }
public SplitGroup(GameObject owner, GameObject split) { this.owner = owner; this.split = split; this.origin = (owner.transform.position + split.transform.position) / 2f; this.elapsedTime = 0f; SpawnRange range = owner.GetComponentInChildren <SpawnRange>(); this.rotationVector = Quaternion.Euler(new Vector3(0f, Random.Range(-180f, 180f), 0f)) * (Vector3.one * range.radius); this.rotationVector.y = 0f; AIUnit ownerUnit = owner.GetComponent <AIUnit>(); AIUnit splitUnit = split.GetComponent <AIUnit>(); if (ownerUnit != null && splitUnit != null && ownerUnit.targetEnemy != null) { splitUnit.targetEnemy = ownerUnit.targetEnemy; } }
public void OnTriggerEnter(Collider other) { if (other.GetComponent <AILineOfSight>() != null || other.GetComponent <AIAttackRange>() != null) { return; } AIUnit attackRange = other.GetComponentInParent <AIUnit>(); if (attackRange != null && attackRange.teamFaction != this.teamFaction && !this.enemies.Contains(attackRange.gameObject)) { this.enemies.Add(attackRange.gameObject); this.enemies.Sort(this); } else { GameUnit unit = other.GetComponent <GameUnit>(); if (unit != null && unit.teamFaction != this.teamFaction && !this.enemies.Contains(unit.gameObject)) { this.enemies.Add(unit.gameObject); this.enemies.Sort(this); } } }
public void Copy(AIUnit original) { this.currentState = original.currentState; this.splitFactor = original.splitFactor; this.mergeFactor = original.mergeFactor; this.attackCooldownFactor = original.attackCooldownFactor; this.attackFactor = original.attackFactor; this.unitManager = original.unitManager; this.currentHealth = original.currentHealth; this.maxHealth = original.maxHealth; this.splitCounter = original.splitCounter; this.minimapCameraRect = original.minimapCameraRect; this.teamFaction = original.teamFaction; this.SetTeamColor(original.teamColorValue); AILineOfSight myLOS = this.GetComponentInChildren <AILineOfSight>(); AILineOfSight originalLOS = original.GetComponentInChildren <AILineOfSight>(); AIAttackRange myAR = this.GetComponentInChildren <AIAttackRange>(); AIAttackRange originalAR = original.GetComponentInChildren <AIAttackRange>(); myLOS.teamFaction = originalLOS.teamFaction; myAR.teamFaction = originalAR.teamFaction; }
public void Copy(AIUnit original) { this.currentState = original.currentState; this.splitFactor = original.splitFactor; this.mergeFactor = original.mergeFactor; this.attackCooldownFactor = original.attackCooldownFactor; this.attackFactor = original.attackFactor; this.unitManager = original.unitManager; this.currentHealth = original.currentHealth; this.maxHealth = original.maxHealth; this.splitCounter = original.splitCounter; this.minimapCameraRect = original.minimapCameraRect; this.teamFaction = original.teamFaction; this.SetTeamColor(original.teamColorValue); AILineOfSight myLOS = this.GetComponentInChildren<AILineOfSight>(); AILineOfSight originalLOS = original.GetComponentInChildren<AILineOfSight>(); AIAttackRange myAR = this.GetComponentInChildren<AIAttackRange>(); AIAttackRange originalAR = original.GetComponentInChildren<AIAttackRange>(); myLOS.teamFaction = originalLOS.teamFaction; myAR.teamFaction = originalAR.teamFaction; }
//Actual update tick public void Tick() { if (this.unitCount <= 0) { //Defeat. No more AI units on the map. Debug.Log("AI Player is defeated."); this.hasLostTheGame = true; this.startAIFlag = false; return; } switch (this.currentFiniteState) { case FSMState.Wait: if (this.selectedUnits.Count > 0) { this.selectedUnits.Clear(); } if (this.unitCount == 1) { //Usually at the start of the game, or when the AI player is on the brink of defeat. Transform child = this.unitContainer.transform.GetChild(this.unitContainer.transform.childCount - 1); AIUnit unit = child.GetComponent <AIUnit>(); AILineOfSight lineOfSight = child.GetComponentInChildren <AILineOfSight>(); AIAttackRange attackRange = child.GetComponentInChildren <AIAttackRange>(); //TODO: Refer to an attribute manager for AI units on what attributes are required. unit.teamFaction = this.teamFaction; lineOfSight.teamFaction = this.teamFaction; attackRange.teamFaction = this.teamFaction; //Always select the unit before doing other AI state machines. this.spawnList.Add(unit); this.currentFiniteState = FSMState.Split; break; } int scoutUnitCount = 0; int splitUnitCount = 0; int mergeUnitCount = 0; foreach (Transform child in this.unitContainer.transform) { if (splitUnitCount > 0) { splitPercentage = splitRatio / splitUnitCount; } else { splitPercentage = splitRatio / 1f; } if (mergeUnitCount > 0) { mergePercentage = mergeRatio / mergeUnitCount; } else { mergePercentage = mergeRatio / 1f; } if (scoutUnitCount > 0) { scoutPercentage = scoutRatio / scoutUnitCount; } else { scoutPercentage = scoutRatio / 1f; } if (this.splitPercentage > this.mergePercentage && this.splitPercentage > this.scoutPercentage) { this.spawnList.Add(child.GetComponent <AIUnit>()); splitUnitCount++; } else if (this.splitPercentage > this.mergePercentage && this.splitPercentage < this.scoutPercentage) { this.selectedUnits.Add(child.GetComponent <AIUnit>()); scoutUnitCount++; } else if (this.splitPercentage < this.mergePercentage && this.splitPercentage > this.scoutPercentage) { this.mergeList.Add(child.GetComponent <AIUnit>()); mergeUnitCount++; } else if (this.splitPercentage < this.mergePercentage && this.splitPercentage < this.scoutPercentage) { if (this.mergePercentage > this.scoutPercentage) { this.mergeList.Add(child.GetComponent <AIUnit>()); mergeUnitCount++; } else { this.selectedUnits.Add(child.GetComponent <AIUnit>()); scoutUnitCount++; } } } this.currentFiniteState = FSMState.Merge; break; case FSMState.Split: if (this.spawnList.Count > 0) { foreach (AIUnit unit in this.spawnList) { if (unit != null && unit.currentState != State.Split) { if (this.unitCount < this.maxUnitCount) { GameObject splitObject = SplitUnit(unit); if (splitObject != null) { this.splitGroupList.Add(new SplitGroup(unit.gameObject, splitObject)); } } else { break; } } } this.spawnList.Clear(); } this.currentFiniteState = FSMState.Wait; break; case FSMState.Scout: Debug.Log("AI player is ready to scout."); if (this.selectedUnits.Count > 0) { for (int i = 0; i < this.selectedUnits.Count; i++) { if (this.selectedUnits[i] != null) { this.selectedUnits[i].SetScoutFlag(); } else { this.selectedUnits.RemoveAt(i); } } this.selectedUnits.Clear(); } if (this.spawnList.Count > 0) { this.currentFiniteState = FSMState.Split; } else { this.currentFiniteState = FSMState.Wait; } break; case FSMState.Merge: if (this.mergeList.Count > 0) { if (this.mergeList.Count > 1) { AIUnit owner = null; AIUnit merge = null; List <AIUnit> removeList = new List <AIUnit>(); for (int i = 0; i < this.mergeList.Count - 1; i++) { if (this.mergeList[i] != null && !removeList.Contains(this.mergeList[i])) { owner = this.mergeList[i]; if (owner.CheckMergeFlag()) { for (int j = i + 1; j < this.mergeList.Count; j++) { merge = this.mergeList[j]; if (merge != null && !removeList.Contains(merge) && !owner.Equals(merge) && owner.level == merge.level) { //TODO: Once unit attribute manager is implemented for the AI player, change the 2f to the actual scaling factor. if (merge.CheckMergeFlag()) { owner.SetMergeFlag(); merge.SetMergeFlag(); this.mergeGroupList.Add(new MergeGroup(owner.gameObject, merge.gameObject, 1.5f)); //ScaleFactor is done here. removeList.Add(owner); removeList.Add(merge); break; } else { continue; } } } } } } removeList.Clear(); } this.mergeList.Clear(); } this.currentFiniteState = FSMState.Scout; break; } foreach (Transform child in this.unitContainer.transform) { if (child != null) { AIUnit unit = child.GetComponent <AIUnit>(); if (unit != null) { unit.Tick(); } } } }
public void Update() { if (this.unitCount <= 0 && !this.startAIFlag && this.isSingleAIPlayer && this.hasLostTheGame) { if (!GameMetricLogger.instance.isShownToScreen) { GameMetricLogger.ShowPrintLog(); } return; } if (this.splitGroupList.Count > 0) { for (int i = 0; i < this.splitGroupList.Count; i++) { SplitGroup splitGroup = this.splitGroupList[i]; if (splitGroup.elapsedTime > 1f) { this.splitGroupList.RemoveAt(i); i--; } else { splitGroup.Update(); splitGroup.elapsedTime += Time.deltaTime; this.splitGroupList[i] = splitGroup; } } } if (this.mergeGroupList.Count > 0) { for (int i = 0; i < this.mergeGroupList.Count; i++) { MergeGroup mergeGroup = this.mergeGroupList[i]; if (mergeGroup.elapsedTime > 1f) { if (mergeGroup.owner != null) { AIUnit unit = mergeGroup.owner.GetComponent <AIUnit>(); unit.previousLevel = unit.level; unit.level++; //TODO: Use the attribute manager to manage the attributes after merging. TierUpgrade tier = this.aiAttributeManager.tiers[unit.level - 1]; //float temp = unit.currentHealth; unit.currentHealth = (int)tier.health; // (temp * tier.health); //temp = unit.maxHealth; unit.maxHealth = (int)tier.health; //(temp * tier.health); unit.attackFactor = tier.attack; unit.mergeFactor = tier.merge; unit.attackCooldownFactor = tier.attackCooldown; unit.splitFactor = tier.split; unit.mergeFactor = tier.merge; unit.speedFactor = tier.speed; } if (mergeGroup.merge != null) { this.removeUnitList.Add(mergeGroup.merge.GetComponent <AIUnit>()); } //MonoBehaviour.Destroy(mergeGroup.merge); this.mergeGroupList.RemoveAt(i); i--; } else { mergeGroup.Update(); mergeGroup.elapsedTime += Time.deltaTime; this.mergeGroupList[i] = mergeGroup; } } } if (this.removeUnitList.Count > 0) { foreach (AIUnit unit in this.removeUnitList) { if (unit != null) { MonoBehaviour.Destroy(unit.gameObject); } } this.removeUnitList.Clear(); } this.unitCount = this.unitContainer.transform.childCount; }
//------------------------------------ private GameObject SplitUnit(AIUnit original) { original.SetSplitFlag(); if (original.currentState == State.Split) { GameObject obj = MonoBehaviour.Instantiate(this.AIUnitPrefab) as GameObject; if (obj != null) { obj.transform.SetParent(original.transform.parent); obj.transform.position = original.transform.position; AIUnit unit = obj.GetComponent<AIUnit>(); if (unit != null) { unit.Copy(original); } } return obj; } return null; }
public void Update() { if (this.attackCooldownCounter >= 0f) { this.attackCooldownCounter -= Time.deltaTime / this.attackCooldownFactor; } //Check if targetEnemy is within sight range. if (this.targetEnemy != null) { if (this.lineOfSight != null) { this.lineOfSight.sphereColliderRigidBody.WakeUp(); if (!this.lineOfSight.enemies.Contains(this.targetEnemy.gameObject)) { this.targetEnemy = null; this.currentState = State.Idle; this.lineOfSight.Clean(); } } else if (this.attackRange != null) { this.attackRange.sphereColliderRigidBody.WakeUp(); if (!this.attackRange.enemies.Contains(this.targetEnemy.gameObject)) { this.targetEnemy = null; this.currentState = State.Idle; this.attackRange.Clean(); } } } if (this.targetEnemy == null && this.currentState != State.Split && this.currentState != State.Merge) { if (this.lineOfSight != null) { this.lineOfSight.sphereColliderRigidBody.WakeUp(); if (this.lineOfSight.enemies.Count > 0) { for (int i = 0; i < this.lineOfSight.enemies.Count; i++) { GameObject enemy = this.lineOfSight.enemies[i]; if (enemy != null) { AIUnit aiUnit = enemy.GetComponentInParent <AIUnit>(); GameUnit playerUnit = enemy.GetComponent <GameUnit>(); if (aiUnit != null || playerUnit != null) { if (aiUnit != null && aiUnit.teamFaction != this.teamFaction) { if (this.agent != null) { this.agent.SetDestination(aiUnit.transform.position); } this.currentState = State.Attack; break; } else if (playerUnit != null && playerUnit.teamFaction != this.teamFaction) { if (this.agent != null) { this.agent.SetDestination(playerUnit.transform.position); } this.currentState = State.Attack; break; } } } } } } } switch (this.currentState) { default: case State.Idle: if (this.targetEnemy != null) { this.currentState = State.Attack; break; } if (this.agent != null) { if (!this.agent.ReachedDestination()) { this.agent.ResetPath(); } } break; case State.Split: if (this.splitCounter > 0f) { this.splitCounter -= Time.deltaTime / this.splitFactor; } else { this.currentState = State.Idle; if (this.agent != null) { this.agent.ResetPath(); } //EnumTeam index value is constant: Player = 0, Computer = 1 SimulationMetricsLogger.Increment(GameMetricOptions.Splits, (this.teamFaction == EnumTeam.Player) ? 0 : 1); } break; case State.Scout: if (this.targetEnemy != null) { this.currentState = State.Attack; break; } if (this.agent != null) { if (this.agent.ReachedDestination()) { this.targetEnemy = null; this.currentState = State.Idle; } } break; case State.Merge: if (this.targetEnemy != null) { this.currentState = State.Attack; break; } if (this.mergeCounter > 0f) { this.mergeCounter -= Time.deltaTime / this.mergeFactor; } else { this.currentState = State.Idle; //EnumTeam index value is constant: Player = 0, Computer = 1 SimulationMetricsLogger.Increment(GameMetricOptions.Merges, (this.teamFaction == EnumTeam.Player) ? 0 : 1); } break; case State.Attack: //Attack logic. if (this.attackCooldownCounter < 0f) { if (this.lineOfSight != null && this.lineOfSight.enemies.Count > 0 && this.attackRange != null && this.attackRange.enemies.Count > 0) { for (int i = 0; i < this.attackRange.enemies.Count; i++) { GameObject enemy = this.attackRange.enemies[i]; if (enemy != null) { AIUnit aiUnit = enemy.GetComponentInParent <AIUnit>() as AIUnit; GameUnit playerUnit = enemy.GetComponent <GameUnit>() as GameUnit; if (aiUnit != null && aiUnit.teamFaction != this.teamFaction) { this.attackCooldownCounter = 1f; this.targetEnemy = aiUnit; aiUnit.TakeDamage(this.attackFactor); //EnumTeam index value is constant: Player = 0, Computer = 1 SimulationMetricsLogger.Increment(GameMetricOptions.Attacks, (this.teamFaction == EnumTeam.Player) ? 0 : 1); SimulationMetricsLogger.Increment(GameMetricOptions.AttackTime, (this.teamFaction == EnumTeam.Player) ? 0 : 1); break; } if (playerUnit != null && playerUnit.teamFaction != this.teamFaction) { this.attackCooldownCounter = 1f; this.targetEnemy = playerUnit; playerUnit.CmdTakeDamage(playerUnit.gameObject, playerUnit.currentHealth - 1); //EnumTeam index value is constant: Player = 0, Computer = 1 SimulationMetricsLogger.Increment(GameMetricOptions.Attacks, (this.teamFaction == EnumTeam.Player) ? 0 : 1); SimulationMetricsLogger.Increment(GameMetricOptions.AttackTime, (this.teamFaction == EnumTeam.Player) ? 0 : 1); break; } } } } } //EnumTeam index value is constant: Player = 0, Computer = 1 SimulationMetricsLogger.Increment(GameMetricOptions.BattleEngagementTime, (this.teamFaction == EnumTeam.Player) ? 0 : 1); break; } if (this.recoveryCounter < 1f) { this.recoveryCounter += Time.deltaTime; } Renderer renderer = this.GetComponent <Renderer>(); if (renderer != null) { renderer.material.color = Color.Lerp(this.takeDamageColor, this.initialColor, this.recoveryCounter); } }