private void CreateModelUnit() { GameObject unit = this[0].gameObject; GameObject modelUnitGO = new GameObject("Model Unit"); //Start out inactive so all components are added before life cycle begins, i.e. Awake, Start etc. modelUnitGO.SetActive(false); var collider = modelUnitGO.AddComponent<SphereCollider>(); collider.isTrigger = true; // make sure model unit is kinematic and does not respond to Unity Gravity var rigidbody = modelUnitGO.AddComponent<Rigidbody>(); rigidbody.isKinematic = true; rigidbody.useGravity = false; // now we need to copy and clone all the relevant components from the group's units to the new model unit (group leader) // copy and clone SteerableUnitComponent, if it exists and is enabled var steerableComponent = unit.GetComponent<SteerableUnitComponent>(); if (steerableComponent != null && steerableComponent.enabled) { var newSteerable = modelUnitGO.AddComponent<SteerableUnitComponent>(); newSteerable.CloneFrom(steerableComponent); } //copy and clone IHeightNavigator component var heightNav = unit.As<IHeightNavigator>(); if (heightNav != null) { var newNav = modelUnitGO.AddComponent(heightNav.GetType()) as IHeightNavigator; newNav.CloneFrom(heightNav); } // copy and clone IDefineSpeed component, if it exists and is enabled var speedComp = unit.As<IDefineSpeed>(); if (speedComp != null) { var newSpeedComp = modelUnitGO.AddComponent(speedComp.GetType()) as IDefineSpeed; newSpeedComp.CloneFrom(speedComp); } // copy and clone PathOptionsComponent, if it exists and is enabled var pathOptions = unit.GetComponent<PathOptionsComponent>(); if (pathOptions != null && pathOptions.enabled) { var newPathOptions = modelUnitGO.AddComponent<PathOptionsComponent>(); newPathOptions.CloneFrom(pathOptions); } // copy and clone SteerToAlignWithVelocity, if it exists and is enabled var steerToAlign = unit.GetComponent<SteerToAlignWithVelocity>(); if (steerToAlign != null && steerToAlign.enabled) { var newSteerToAlign = modelUnitGO.AddComponent<SteerToAlignWithVelocity>(); newSteerToAlign.CloneFrom(steerToAlign); } // copy and cone PathVisualizer, if it exists and is enabled var pathVisualizer = unit.GetComponent<PathVisualizer>(); if (pathVisualizer != null && pathVisualizer.enabled) { var newPathVisualizer = modelUnitGO.AddComponent<PathVisualizer>(); newPathVisualizer.CloneFrom(pathVisualizer); } // copy and clone SteerForPathComponent, if it exists and is enabled var steerForPath = unit.GetComponent<SteerForPathComponent>(); if (steerForPath != null && steerForPath.enabled) { var newSteerForPath = modelUnitGO.AddComponent<SteerForPathComponent>(); newSteerForPath.CloneFrom(steerForPath); } // copy and clone UnitComponent, if it exists and is enabled var unitComp = unit.GetComponent<UnitComponent>(); if (unitComp != null && unitComp.enabled) { var newUnitComponent = modelUnitGO.AddComponent<UnitComponent>(); newUnitComponent.CloneFrom(unitComp); newUnitComponent.isSelectable = false; newUnitComponent.selectionVisual = null; newUnitComponent.enabled = true; } // copy and clone SteerForVectorFieldComponent, if it exists and is enabled var steerForVectorField = unit.GetComponent<SteerForVectorFieldComponent>(); if (steerForVectorField != null && steerForVectorField.enabled) { var newSteerForVector = modelUnitGO.AddComponent<SteerForVectorFieldComponent>(); newSteerForVector.CloneFrom(steerForVectorField); newSteerForVector.arrivalRadiusMargin = 0f; newSteerForVector.arrivalDistance = 0.2f; } // copy and clone SteeringController, if it exists and is enabled var steeringController = unit.GetComponent<SteeringController>(); if (steeringController != null && steeringController.enabled) { modelUnitGO.AddComponent<SteeringController>(); } // copy Apex Component Master var componentMaster = unit.GetComponent<ApexComponentMaster>(); if (componentMaster != null && componentMaster.enabled) { modelUnitGO.AddComponent<ApexComponentMaster>(); } // active the model unit here at last - also make sure a UnitFacade is made and that it knows of this group modelUnitGO.SetActive(true); _modelUnit = modelUnitGO.GetUnitFacade(); _modelUnit.transientGroup = this; if (nextNodePosition.HasValue) { // if there is a path and the next node position is valid, then place the model unit at the same position as the nearest unit in the group compared to the next node position Vector3 nearestPos = Vector3.zero; float shortestDistance = float.MinValue; for (int i = 0; i < this.count; i++) { Vector3 pos = this[i].position; float distance = (pos - nextNodePosition.Value).sqrMagnitude; if (distance < shortestDistance) { shortestDistance = distance; nearestPos = pos; } } _modelUnit.transform.position = nearestPos; } else { // if there is no path or the next node position is not valid, just place model unit at the center of the group _modelUnit.transform.position = GetGroupCenterOfGravity(); } _modelUnit.transform.forward = this[0].forward; }