// Carry out one action; currently moves the NPC character. public override void carryOutAction() { // Find the simulation controller script. cScript = GameObject.FindWithTag("MainCamera").GetComponent<cSimulationController>(); cScript2 = GameObject.FindWithTag("thePlayer").GetComponent<cPlayerController>(); // If it is NPC's turn to do something ... if (cScript.AITurn > 0) { if (!cScript.flockingOn || mFlockingData.mRole == FLOCK_ROLE.leader) { if (cScript2.mKinematicData.mPosition != null) if (Physics.Raycast(transform.position, cScript2.mKinematicData.mPosition[cScript2.mKinematicData.mPosition.Count-1]-transform.position, Vector3.Distance(transform.position, cScript2.mKinematicData.mPosition[cScript2.mKinematicData.mPosition.Count-1]), 9)) { //Debug.Log("theNPC" + tag + ": Can't see the player! My position: " + transform.position + " Player's position: " + cScript2.mKinematicData.mPosition[cScript2.mKinematicData.mPosition.Count-1]); updateMovementData(); } else { // Based on current simulation type, AI behavior, and selected AI behavior strategy, get new // kinematic and/or steering data and update movement data accordingly. switch(cScript.currentSimulationCategory) { case SIMULATION.KINEMATIC_MOVEMENT: /* switch((KINEMATIC_MOVEMENT)action) { case KINEMATIC_MOVEMENT.Do_Nothing: mKinematicData = mKinematicMovementStrategies[0].getKinematicData(ref mKinematicData); break; case KINEMATIC_MOVEMENT.Wander: mKinematicData = mKinematicMovementStrategies[1].getKinematicData(ref mKinematicData); updateMovementData(); break; case KINEMATIC_MOVEMENT.Seek: seTactic.getSteeringData(ref mKinematicData); updateMovementData(); break; case KINEMATIC_MOVEMENT.Flee: mKinematicData = flTactic.getSteeringData(ref mKinematicData); updateMovementData(); break; case KINEMATIC_MOVEMENT.Arrive: arTactic.getSteeringData(ref mKinematicData); updateMovementData(); break; }*/ bool lBehaviourFound = false; int i = 0; while (i < 10 && lBehaviourFound == false) { if (mActiveKinematicMovements[i] == true) { mKinematicMovementStrategies[i].getKinematicData(ref mKinematicData); updateMovementData(); lBehaviourFound = true; } i++; } break; case SIMULATION.STEERING_BEHAVIOR: /* switch((STEERING_BEHAVIOR)action) { case STEERING_BEHAVIOR.Do_Nothing: mSteeringBehaviourStrategies[0].getSteeringData(ref mKinematicData, ref mSteeringData); break; case STEERING_BEHAVIOR.Seek: mSteeringBehaviourStrategies[1].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; case STEERING_BEHAVIOR.Flee: mSteeringBehaviourStrategies[2].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; case STEERING_BEHAVIOR.Arrive: mSteeringBehaviourStrategies[3].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; case STEERING_BEHAVIOR.Align: mSteeringBehaviourStrategies[4].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; case STEERING_BEHAVIOR.Match_Velocity: mSteeringBehaviourStrategies[5].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; case STEERING_BEHAVIOR.Pursue: mSteeringBehaviourStrategies[6].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; case STEERING_BEHAVIOR.Evade: mSteeringBehaviourStrategies[7].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; case STEERING_BEHAVIOR.Face: mSteeringBehaviourStrategies[8].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; case STEERING_BEHAVIOR.Wander: mSteeringBehaviourStrategies[9].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); break; }*/ bool lBehaviourFound2 = false; int j = 0; while (j < 10 && lBehaviourFound2 == false) { if (mActiveSteeringBehaviours[j] == true) { mSteeringBehaviourStrategies[j].getSteeringData(ref mKinematicData, ref mSteeringData); updateMovementData(); lBehaviourFound2 = true; } j++; } break; } } } //Debug.Log("Boid Alignment_BF" + this.transform.forward); if (cScript.flockingOn && mFlockingData.mRole == FLOCK_ROLE.boid) { //Debug.Log("Boid Alignment_F" + this.transform.forward); //Debug.Log("Boid facing: " + mFlockingData.mBoidFacing); if (mFlockingData.mBoidVelocity.magnitude > mKinematicData.mMaxVelocity) { mFlockingData.mBoidVelocity.Normalize(); mFlockingData.mBoidVelocity *= mKinematicData.mMaxVelocity; } //Debug.Log("Boid data:" + mFlockingData.mBoidVelocity + " - " + mFlockingData.mBoidFacing); Vector3 lTmpVector = mKinematicData.mPosition[mKinematicData.mPosition.Count-1] + mFlockingData.mBoidVelocity * cScript.currentSimulationSpeed/100; mKinematicData.mPosition.Insert(mKinematicData.mPosition.Count, lTmpVector); if (mFlockingData.mBoidVelocity.magnitude > 0) { mFlockingData.mBoidFacing = mFlockingData.mBoidVelocity; } //Debug.Log("Boid facing: " + mFlockingData.mBoidFacing); Quaternion ltq = Quaternion.identity; ltq.SetLookRotation(mFlockingData.mBoidFacing); //Debug.Log("FlockOrient" + ltq); // Update the model accordingly. this.transform.position = mKinematicData.mPosition[mKinematicData.mPosition.Count-1]; this.transform.rotation = Quaternion.LookRotation(mFlockingData.mBoidFacing); } cScript.AITurn--; } }
/// <summary> /// Updates the movement data for the player; position and orientation. /// </summary> public void updateMovementData() { // Set the latest position of the player to be the current position. if (mKinematicData.mPosition != null) mKinematicData.mPosition[mKinematicData.mPosition.Count-1] = this.transform.position; // Find the simulation controller script. mSimulationController = GameObject.FindWithTag("MainCamera").GetComponent<cSimulationController>(); cGUIControllerSimulation mGUIController = Camera.main.GetComponent<cGUIControllerSimulation>(); // Store current velocity for the player. Vector3 tmpVel = mKinematicData.mVelocity; // Get the data from the input device. float zVel = Input.GetAxisRaw("Vertical"); float xVel = Input.GetAxisRaw("Horizontal"); // If user does not move the character, just set its velocity to zero. if (zVel == 0.0f && xVel == 0.0f) { mKinematicData.mVelocity = Vector3.zero; mActionTaken = true; } // Otherwise, if camera is not third person player camera ... else if (mGUIController.mGUI_containers[4].target != 3) { // Add the value from z axis of the input device to current velocity, // clamp the resulting value to maximum velocity, // update player velocity, and confirm action. if (zVel != 0.0f) tmpVel.z += zVel; else tmpVel.z = 0.0f; if (tmpVel.z > mKinematicData.mMaxVelocity) tmpVel.z = mKinematicData.mMaxVelocity; mKinematicData.mVelocity += tmpVel; mActionTaken = true; // Add the value from x axis of the input device to current velocity, // clamp the resulting value to maximum velocity, // update player velocity, and confirm action. if (xVel != 0.0f) tmpVel.x += xVel; else tmpVel.x = 0.0f; if (tmpVel.x > mKinematicData.mMaxVelocity) tmpVel.x = mKinematicData.mMaxVelocity; mKinematicData.mVelocity += tmpVel; mActionTaken = true; } // Otherwise if camera is third person camera... else { // Get current movement direction. tmpVel = transform.forward; // Add the positive value from z axis of the input device to current velocity // and confirm action if (zVel > 0.0f) { tmpVel *= zVel; mKinematicData.mVelocity = tmpVel; mActionTaken = true; } // Rotate the player character based on the value from x axis of the input device // both when the player is still and when it is moving forward, // and confirm action if (xVel != 0.0f) { if (mKinematicData.mVelocity != Vector3.zero) mKinematicData.mVelocity = Quaternion.AngleAxis(xVel*5, Vector3.up) * mKinematicData.mVelocity; else { mKinematicData.mVelocity = Quaternion.AngleAxis(xVel*5, Vector3.up) * transform.forward; mKinematicData.mOrientation = getNewOrientation(mKinematicData); mKinematicData.mVelocity = Vector3.zero; } mActionTaken = true; } } // If player has moved ... if (mActionTaken) { // Update velocity. mKinematicData.mVelocity.Normalize(); mKinematicData.mVelocity *= mKinematicData.mMaxVelocity; // Update orientation. if (mKinematicData.mVelocity != Vector3.zero) mKinematicData.mOrientation = getNewOrientation(mKinematicData); // If not already enabled, enable the tarce renderer. if(mTraceRenderer != null) if(mTraceRenderer.enabled == false) mTraceRenderer.enabled = true; // Update the position data, and set the position and rotation of the actual player character's transform; if (mKinematicData.mPosition != null) { if (mKinematicData.mPosition.Count >= mKinematicData.mArrayListSize) { mKinematicData.mPosition.RemoveAt(0); } Vector3 lTmpVector = mKinematicData.mPosition[mKinematicData.mPosition.Count-1] + mKinematicData.mVelocity * mSimulationController.currentSimulationSpeed / 100; mKinematicData.mPosition.Insert(mKinematicData.mPosition.Count, lTmpVector); mKinematicData.mOrientation *= mKinematicData.mRotation; this.transform.position = mKinematicData.mPosition[mKinematicData.mPosition.Count-1]; this.transform.rotation = mKinematicData.mOrientation; // If steering data is on, update velocity and rotation based on linear and angular acceleration values. if (mSimulationController.currentSimulationCategory == SIMULATION.STEERING_BEHAVIOR) { mKinematicData.mVelocity += mSteeringData.mLinear; if (mSteeringData.mAngular != Quaternion.identity) { mKinematicData.mRotation = mKinematicData.mRotation * mSteeringData.mAngular; } if (mKinematicData.mVelocity.magnitude > mKinematicData.mMaxVelocity) { mKinematicData.mVelocity.Normalize(); mKinematicData.mVelocity *= mKinematicData.mMaxVelocity; } } // Set the latest position of the kinematic data to be the actual current position of the player character mKinematicData.mPosition[mKinematicData.mPosition.Count-1] = transform.position; } } // Update trace renderer data if (mKinematicData.mPosition != null && mTraceHu != null) { // Clear the queue of positions used to draw the trace mTraceHu.Clear(); // If the amount of position sis smaller than trace size, clamp the tracesize. if(mTraceSize > mKinematicData.mPosition.Count) mTraceSize = mKinematicData.mPosition.Count; // Fill the queue of positions used to draw the trace based on kinematic data. for (int i = mKinematicData.mPosition.Count-1; i >= mKinematicData.mPosition.Count - mTraceSize; i--) { Vector3 lTmpPosition2 = mKinematicData.mPosition[i]; lTmpPosition2.y += 0.2f; mTraceHu.Enqueue(lTmpPosition2); } // Set the size of the trace in the trace renderer. mTraceRenderer.SetVertexCount(0); mTraceRenderer.SetVertexCount(mTraceSize); // Render the trace and at the same time empty the positions queue. for (int i = 0; i < mTraceSize; i++) { if (mTraceHu.Count > 0) mTraceRenderer.SetPosition(i, (Vector3) mTraceHu.Dequeue()); } } }
void Start() { mActiveKinematicMovements = new bool[10]; mKinematicMovementStrategies = new acKinematicMovement[10]; mActiveKinematicMovements[0] = true; for (int i = 1; i < 10; i++) mActiveKinematicMovements[i] = false; mKinematicMovementStrategies[0] = new cDoNothingKM(); mKinematicMovementStrategies[1] = new cSeekMillingtonFunge(); mKinematicMovementStrategies[2] = new cFleeMillingtonFunge(); mKinematicMovementStrategies[3] = new cArriveMillingtonFunge(); mKinematicMovementStrategies[4] = new cAlignKMMillingtonFunge(); mKinematicMovementStrategies[5] = new cMatchVelocityKMMillingtonFunge(); mKinematicMovementStrategies[6] = new cPursueKMMillingtonFunge(); mKinematicMovementStrategies[7] = new cEvadeKMMillingtonFunge(); mKinematicMovementStrategies[8] = new cFaceKMMillingtonFunge(); mKinematicMovementStrategies[9] = new cWanderMillingtonFunge(); mActiveSteeringBehaviours = new bool[10]; mSteeringBehaviourStrategies = new acSteeringBehaviors[10]; mActiveSteeringBehaviours[0] = true; for (int i = 1; i < 10; i++) mActiveSteeringBehaviours[i] = false; mSteeringBehaviourStrategies[0] = new cDoNothingSB(); mSteeringBehaviourStrategies[1] = new cSeekSBMillingtonFunge(); mSteeringBehaviourStrategies[2] = new cFleeSBMillingtonFunge(); mSteeringBehaviourStrategies[3] = new cArriveSBMillingtonFunge(); mSteeringBehaviourStrategies[4] = new cAlignSBMillingtonFunge(); mSteeringBehaviourStrategies[5] = new cMatchVelocitySBMillingtonFunge(); mSteeringBehaviourStrategies[6] = new cPursueSBMillingtonFunge(); mSteeringBehaviourStrategies[7] = new cEvadeSBMillingtonFunge(); mSteeringBehaviourStrategies[8] = new cFaceSBMillingtonFunge(); mSteeringBehaviourStrategies[9] = new cWanderSBMillingtonFunge(); // Find the simulation controller script. cScript = GameObject.FindWithTag("MainCamera").GetComponent<cSimulationController>(); // Get current action the NPC should follow. action = cScript.currentAIBehavior; // Initialize kinematic data. mKinematicData.mArrayListSize = 1000; mKinematicData.mPosition = new List<Vector3>(); mKinematicData.mPosition.Add(transform.position); mKinematicData.mVelocity = Vector3.zero; mKinematicData.mOrientation = transform.rotation; mKinematicData.mRotation = Quaternion.identity; // Initialize steering data. mSteeringData.mLinear = Vector3.zero; mSteeringData.mAngular = Quaternion.identity; // Initialize flocking data. mFlockingData.mRole = FLOCK_ROLE.boid; mFlockingData.mCohesionWeight = 50; mFlockingData.mAlignmentWeight = 50; mFlockingData.mSeparationWeight = 50; mFlockingData.mTargetLoyalty = 50; mFlockingData.mBoidVelocity = Vector3.zero; mFlockingData.mBoidFacing = Vector3.zero; mTraceAI = new Queue(); //mTraceHu = new Queue(); mTraceSize = 20; int lTagNumber = int.Parse(tag.Substring(6)); //setLineTracer(); lLineAI = (LineRenderer) this.gameObject.AddComponent<LineRenderer>(); mTraceColor = new Color(1.0f/(lTagNumber+1), 0.0f, 0.0f, 1.0f); setLineTracer(); if (lLineAI != null) lLineAI.enabled = false; /* for (int i = 0; i < mKinematicData.mArrayListSize; i++) { mKinematicData.mPosition.Insert(i, this.transform.position); }*/ }
/// <summary> /// Actions takes when starting this instance.. /// </summary> void Start() { // Find the simulation controller script. mSimulationController = GameObject.FindWithTag("MainCamera").GetComponent<cSimulationController>(); // Get current action the player should follow. action = mSimulationController.currentAIBehavior; // Initialize kinematic data. mKinematicData.mArrayListSize = 1000; mKinematicData.mPosition = new List<Vector3>(); mKinematicData.mPosition.Add(transform.position); mKinematicData.mVelocity = Vector3.zero; mKinematicData.mOrientation = transform.rotation; mKinematicData.mRotation = Quaternion.identity; // Initialize steering data. mSteeringData.mLinear = Vector3.zero; mSteeringData.mAngular = Quaternion.identity; // Initialize trace settings and renderer. mTraceHu = new Queue(); mTraceSize = 20; mTraceRenderer = (LineRenderer) this.gameObject.AddComponent<LineRenderer>(); mTraceRenderer.SetWidth(0.05f, 0.05f); mTraceRenderer.SetVertexCount(mTraceSize); mMaterial = Resources.Load("Materials/goo", typeof(Material)) as Material; mTraceRenderer.material = mMaterial; mTraceRenderer.material.color = Color.green; mTraceRenderer.enabled = false; }
/// <summary> /// Update called in every frame. /// </summary> void OnGUI() { // Set up the GUI skin. GUI.skin = mSkinToApply; // Update the simulation controller script. mSimulationController = GameObject.FindWithTag("MainCamera").GetComponent<cSimulationController>(); // Update the player controller script. mPlayerController = GameObject.FindWithTag("thePlayer").GetComponent<cPlayerController>(); // If trace data is not set yet, set it up. if (traceSet == false) { for (int i = 0; i < mNPCmarkers.Length; i++) { GameObject tmpNPC = GameObject.FindWithTag("theNPC" + i); if (tmpNPC != null) { mNPCController = tmpNPC.GetComponent<cNPCController>(); mNPCController.mTraceColor = new Color(1.0f/(i+1), 0.0f, 0.0f, 1.0f); mNPCController.setLineTracer(); } } traceSet = true; } // Set up the trace length. if (mTraceLength != "") mPlayerController.mTraceSize = int.Parse(mTraceLength); // Set current trace size of each NPC to the selected trace size. for (int i = 0; i < mSimulationController.numberOfnpcs; i++) { GameObject tmpNPC = GameObject.FindWithTag("theNPC" + i); if (tmpNPC != null) { mNPCController = tmpNPC.GetComponent<cNPCController>(); if (mTraceLength != "") mNPCController.mTraceSize = int.Parse(mTraceLength); } } // Construct the Simulation settings GUI element. if(mGUI_containers[4].expanded) { GUILayout.BeginArea(mGUI_containers[4].position, mBackground); } else GUILayout.BeginArea(mGUI_containers[4].position_not_expanded, mBackground); GUILayout.BeginVertical(GUI.skin.customStyles[0]); mGUI_containers[4].expanded = GUILayout.Toggle(mGUI_containers[4].expanded, new GUIContent ("Simulation settings", "tool tip"), GUILayout.Width(140)); bool expand_overlap = false; for (int i = 1; i < 6; i++) { if (i != 4) { if (mGUI_containers[i].expanded) { if (RectsOverap(mGUI_containers[4].position, mGUI_containers[i].position)) { expand_overlap = true; } } else { if (RectsOverap(mGUI_containers[4].position, mGUI_containers[i].position_not_expanded)) { expand_overlap = true; } } } } if (expand_overlap) { mGUI_containers[4].expanded = false; } if (mGUI_containers[4].expanded) { GUILayout.Box(mLogoTexture, new GUIStyle()); GUI.SetNextControlName("GUI_NoNPCs"); mGUI_NumberOfNPCs = GUILayout.TextField(mGUI_NumberOfNPCs); if ((Event.current.type == EventType.KeyUp) && (Event.current.keyCode == KeyCode.Return)) { GUI.SetNextControlName(""); GUI.FocusControl(""); } else if (!string.Equals(GUI.GetNameOfFocusedControl(), "GUI_NoNPCs")) { if (int.TryParse(mGUI_NumberOfNPCs, out mNewNumberOfNPCs)) { if(mNewNumberOfNPCs != mNumberOfNPCs && mNewNumberOfNPCs >= 0 && mNewNumberOfNPCs < MAXNUMOFNPCS) { mSimulationController.destroyActors(); mSimulationController.numberOfnpcs = mNewNumberOfNPCs; mSimulationController.initSimulation(); mIndividualAIBehaviourMarkers = new int[mNewNumberOfNPCs]; for (int i = 0; i < mNewNumberOfNPCs; i++) { mIndividualAIBehaviourMarkers[i] = 0; } for (int i = 0; i < mNPCmarkers.Length; i++) { Destroy(mNPCmarkers[i]); } mNPCmarkers = new Texture2D[mNewNumberOfNPCs]; for (int i = 0; i < mNPCmarkers.Length; i++) { GameObject tmpNPC = GameObject.FindWithTag("theNPC" + i); mNPCController = tmpNPC.GetComponent<cNPCController>(); mNPCmarkers[i] = new Texture2D(24, 24); for (int j = 0; j < 24; j++) for (int k = 0; k < 24; k++) mNPCmarkers[i].SetPixel(j, k, new Color(1.0f/(i+1), 0.0f, 0.0f, 1.0f)); mNPCmarkers[i].Apply(); } mNumberOfNPCs = mNewNumberOfNPCs; mGUI_containers[5].position = new Rect (mGUI_containers[5].position.x, mGUI_containers[5].position.y, mGUI_containers[5].position.width,mNumberOfNPCs*0.06f*Screen.height); } mGUI_NumberOfNPCs = mNumberOfNPCs.ToString(); } } // Create the title for speed adjustment slider. GUILayout.Label ("Current simulation speed: " + mCurrentSpeed); // Create the slider for adjusting simulation speed. float lNewSpeed = GUILayout.HorizontalSlider((int)mCurrentSpeed, 0.0f, mMaxSpeed); if (mCurrentSpeed != lNewSpeed) { mCurrentSpeed = lNewSpeed; mCurrentAIBehaviourChanged = true; } // Create the title for the selection grid for simulation type. GUILayout.Label("Simulation type: "); // Create the selection grid. int lTmp = GUILayout.SelectionGrid(mSelectionGridIntSimulationType, mSelectionStringsSimulationType, 1); if (lTmp != mSelectionGridIntSimulationType) { mSimulationController.currentSimulationCategory = (SIMULATION) lTmp; mSimulationController.currentAIBehavior = 0; mSelectionGridIntAIBehaviour = 0; mCurrentAIBehaviourChanged = true; mCurrentSimulationTypeChanged = true; mSelectionGridIntSimulationType = lTmp; } mFlocking = GUILayout.Toggle(mFlocking, "Flocking", GUILayout.Width(140)); mSimulationController.flockingOn = mFlocking; mTraceLength = GUILayout.TextField(mTraceLength); mSelectionGridIntCamViews[3] = GUILayout.SelectionGrid(mSelectionGridIntCamViews[3], mSelectionStringsCamViews, 4); mGUI_containers[4].target = mSelectionGridIntCamViews[3]+1; if (GUILayout.Button("Quit simulation", GUI.skin.button)) { // ToDo: find better solution for iOS build. Application.Quit(); } } GUILayout.EndVertical(); GUILayout.EndArea (); // GUI area for individual NPCs. if(mGUI_containers[5].expanded) { GUILayout.BeginArea(mGUI_containers[5].position, mBackground); } else GUILayout.BeginArea(mGUI_containers[5].position_not_expanded, mBackground); mScrollPositionIndividualNPCs = GUILayout.BeginScrollView(mScrollPositionIndividualNPCs); GUILayout.BeginVertical(GUI.skin.customStyles[0]); mGUI_containers[5].expanded = GUILayout.Toggle(mGUI_containers[5].expanded, "Individual NPC settings", GUILayout.Width(240)); bool expand_overlap2 = false; for (int i = 1; i < 6; i++) { if (i != 5) { if (mGUI_containers[i].expanded) { if (RectsOverap(mGUI_containers[5].position, mGUI_containers[i].position)) { expand_overlap2 = true; } } else { if (RectsOverap(mGUI_containers[5].position, mGUI_containers[i].position_not_expanded)) { expand_overlap2 = true; } } } } if (expand_overlap2) { mGUI_containers[5].expanded = false; } if (mGUI_containers[5].expanded) { for (int i = 0; i < mSimulationController.numberOfnpcs; i++) { GUILayout.BeginHorizontal(); if (mColorPickerVisible[i] == false) { GUILayout.Label (mSimulationController.npcs[i].tag); bool tmp = GUILayout.Toggle(mSimulationController.npcs[i].active, "Active"); mSimulationController.npcs[i].SetActiveRecursively(tmp); if (GUILayout.Button(mNPCmarkers[i], GUI.skin.button, GUILayout.Height(18), GUILayout.Width(18))) { mColorPickerVisible[i] = true; mColorChangeTarget = i; mSelectedColor = mNPCmarkers[i].GetPixel(0,0); } GameObject tmpNPC = GameObject.FindWithTag("theNPC" + i); if (tmpNPC != null) { mNPCController = tmpNPC.GetComponent<cNPCController>(); } int lTmp2 = 0; switch (mSimulationController.currentSimulationCategory) { case SIMULATION.KINEMATIC_MOVEMENT: foreach (KINEMATIC_MOVEMENT km in KINEMATIC_MOVEMENT.GetValues(typeof(KINEMATIC_MOVEMENT))) { if ((int)km < mNPCController.mActiveKinematicMovements.Length) mNPCController.mActiveKinematicMovements[(int)km] = GUILayout.Toggle(mNPCController.mActiveKinematicMovements[(int)km], km.ToString(), GUILayout.Width(0.025f*Screen.width)); } break; case SIMULATION.STEERING_BEHAVIOR: foreach (STEERING_BEHAVIOR sb in STEERING_BEHAVIOR.GetValues(typeof(STEERING_BEHAVIOR))) { if ((int)sb < mNPCController.mActiveKinematicMovements.Length) mNPCController.mActiveSteeringBehaviours[(int)sb] = GUILayout.Toggle(mNPCController.mActiveSteeringBehaviours[(int)sb], sb.ToString(), GUILayout.Width(0.025f*Screen.width));; } break; } if (mNPCController.mFlockingData.mRole == FLOCK_ROLE.leader || mSimulationController.flockingOn == false) { mIndividualAIBehaviourMarkers[i] = lTmp2; } int tmpSel; if (mNPCController.mFlockingData.mRole == FLOCK_ROLE.boid) tmpSel = 0; else tmpSel = 1; int lTmp3 = GUILayout.SelectionGrid(tmpSel, mSelectionStringsFocking, 2, GUILayout.Width(0.10f*Screen.width)); if (tmpSel == 0 && lTmp3 == 1) mSimulationController.flockingLeadersCount++; if (tmpSel == 1 && lTmp3 == 0) mSimulationController.flockingLeadersCount--; if (mSimulationController.flockingOn) { if (lTmp3 == 0) { mNPCController.mFlockingData.mRole = FLOCK_ROLE.boid; mNPCController.setAction(0); mIndividualAIBehaviourMarkers[i] = 0; } else mNPCController.mFlockingData.mRole = FLOCK_ROLE.leader; } } else { GUILayout.Label (mSimulationController.npcs[i].tag); mSelectedColor = RGBSlider (new Rect (10,10,100,30), mSelectedColor); mColorBoxTexture = new Texture2D(24, 24); for (int ii = 0; ii < 24; ii++) for (int j = 0; j < 24; j++) mColorBoxTexture.SetPixel(ii, j, mSelectedColor); mColorBoxTexture.Apply(); GUILayout.Box(mColorBoxTexture, new GUIStyle()); if (GUILayout.Button("Change the Color")) { for (int j = 0; j < 24; j++) for (int k = 0; k < 24; k++) mNPCmarkers[mColorChangeTarget].SetPixel(j, k, mSelectedColor); mNPCmarkers[mColorChangeTarget].Apply(); GameObject tmpNPC = GameObject.FindWithTag("theNPC" + mColorChangeTarget); if (tmpNPC != null) { mNPCController = tmpNPC.GetComponent<cNPCController>(); mNPCController.lLineAI.material.color = mSelectedColor; } mColorPickerVisible[i] = false; } } GUILayout.EndHorizontal(); GUILayout.Space(5.0f); } } GUILayout.EndVertical(); GUILayout.EndScrollView(); GUILayout.EndArea (); // GUI areas for mini cameras. bool[] expand_overlaps = new bool[3]; for (int it = 1; it < 4; it++) { if(mGUI_containers[it].expanded) { GUILayout.BeginArea(mGUI_containers[it].position, mBackground); } else GUILayout.BeginArea(mGUI_containers[it].position_not_expanded, mBackground); GUILayout.BeginVertical(mSkinToApply.customStyles[0]); mGUI_containers[it].expanded = GUILayout.Toggle(mGUI_containers[it].expanded, "Camera " + it, GUILayout.Width(80)); expand_overlaps[it-1] = false; for (int ih = 1; ih < 6; ih++) { if (ih != it) { if (mGUI_containers[ih].expanded) { if (RectsOverap(mGUI_containers[it].position, mGUI_containers[ih].position)) { expand_overlaps[it-1] = true; } } else { if (RectsOverap(mGUI_containers[it].position, mGUI_containers[ih].position_not_expanded)) { expand_overlaps[it-1] = true; } } } } if (expand_overlaps[it-1]) { mGUI_containers[it].expanded = false; } if (mGUI_containers[it].expanded) { int tmpSelection; int tmpCam = 128; if (mSelectionGridIntCamSizes[it-1] == 1) tmpCam = 128; else if (mSelectionGridIntCamSizes[it-1] == 2) tmpCam = 256; if (mSelectionGridIntCamSizes[it-1] == 3) tmpCam = 512; tmpSelection = mSelectionGridIntCamSizes[it-1]; mSelectionGridIntCamSizes[it-1] = GUILayout.SelectionGrid(mSelectionGridIntCamSizes[it-1], mSelectionStringsCamSizes, 3); Rect tmpRect = new Rect(mGUI_containers[it].position.x, mGUI_containers[it].position.y, mGUI_containers[it].position.width, mGUI_containers[it].position.height); int tmpCam2 = tmpCam; if(mSelectionGridIntCamSizes[it-1] == 0) { tmpCam2 = 108; tmpRect.width = 130; tmpRect.height = 210; } if(mSelectionGridIntCamSizes[it-1] == 1) { tmpCam2 = 236; tmpRect.width = 258; tmpRect.height = 338; } if(mSelectionGridIntCamSizes[it-1] == 2) { tmpCam2 = 492; tmpRect.width = 514; tmpRect.height = 594; } bool overlap = false; for (int ig = 1; ig < 6; ig++) { if (ig != it) { if (mGUI_containers[ig].expanded) { if (RectsOverap(tmpRect, mGUI_containers[ig].position)) { overlap = true; } } else { if (RectsOverap(tmpRect, mGUI_containers[ig].position_not_expanded)) { overlap = true; } } } } if (!overlap) { Rect tmpRec = new Rect(0, 0, tmpCam2, tmpCam2); GUILayout.Label(mMiniCameras[it-1], GUILayout.Width(tmpCam2), GUILayout.Height(tmpCam2)); if (Event.current.type == EventType.Repaint) { tmpRec = GUILayoutUtility.GetLastRect(); } else { tmpRec = new Rect(0, 0, 0, 0); } Graphics.DrawTexture(tmpRec, mMiniCameras[it-1], mMiniCameraRTMaterial); mGUI_containers[it].position.width = tmpRect.width; mGUI_containers[it].position.height = tmpRect.height; } else { mSelectionGridIntCamSizes[it-1] = tmpSelection; GUILayout.Label(mMiniCameras[it-1], GUILayout.Width(tmpCam), GUILayout.Height(tmpCam)); } mSelectionGridIntCamViews[it-1] = GUILayout.SelectionGrid(mSelectionGridIntCamViews[it-1], mSelectionStringsCamViews, 4); mGUI_containers[it].target = mSelectionGridIntCamViews[it-1]+1; } GUILayout.EndVertical(); GUILayout.EndArea(); } // Tool tip for GUI elements. Vector2 mousePosition = Input.mousePosition; if (GUI.tooltip != "") GUI.Label(new Rect(mousePosition.x, (Screen.height-mousePosition.y), 100, 40), GUI.tooltip, mSkinToApply.customStyles[0]); // GUI elements dragging logic. for (int j = 1; j < 6; j++) { if (mGUI_containers[j].expanded) { if (mCurrentlyDragging == -1 && Event.current.type == EventType.MouseDown && PointIsWithinRect( Event.current.mousePosition, mGUI_containers[j].position) ) { mCurrentlyDragging = j; mDragOffset.x = Event.current.mousePosition.x - mGUI_containers[j].position.x; mDragOffset.y = Event.current.mousePosition.y - mGUI_containers[j].position.y; } else if( Event.current.type == EventType.MouseDrag && mCurrentlyDragging == j) { mCurrentlyDragged = new Rect( Event.current.mousePosition.x - mDragOffset.x, Event.current.mousePosition.y - mDragOffset.y, mGUI_containers[j].position.width, mGUI_containers[j].position.height ); bool overlap = false; for (int ia = 1; ia < 6; ia++) { if (ia != j) { if (mGUI_containers[ia].expanded) { if (RectsOverap(mCurrentlyDragged, mGUI_containers[ia].position)) { overlap = true; } } else { if (RectsOverap(mCurrentlyDragged, mGUI_containers[ia].position_not_expanded)) { overlap = true; } } } } if (!overlap) { mGUI_containers[j].position = mCurrentlyDragged; mGUI_containers[j].position_not_expanded.x = mGUI_containers[j].position.x; mGUI_containers[j].position_not_expanded.y = mGUI_containers[j].position.y;; } } else if( Event.current.type == EventType.MouseUp ) { mCurrentlyDragging = -1; } } else { if (mCurrentlyDragging == -1 && Event.current.type == EventType.MouseDown && PointIsWithinRect( Event.current.mousePosition, mGUI_containers[j].position_not_expanded) ) { mCurrentlyDragging = j; mDragOffset.x = Event.current.mousePosition.x - mGUI_containers[j].position_not_expanded.x; mDragOffset.y = Event.current.mousePosition.y - mGUI_containers[j].position_not_expanded.y; } else if( Event.current.type == EventType.MouseDrag && mCurrentlyDragging == j) { mCurrentlyDragged = new Rect( Event.current.mousePosition.x - mDragOffset.x, Event.current.mousePosition.y - mDragOffset.y, mGUI_containers[j].position_not_expanded.width, mGUI_containers[j].position_not_expanded.height ); bool overlap = false; for (int iu = 1; iu < 6; iu++) { if (iu != j) { if (mGUI_containers[iu].expanded) { if (RectsOverap(mCurrentlyDragged, mGUI_containers[iu].position)) { overlap = true; } } else { if (RectsOverap(mCurrentlyDragged, mGUI_containers[iu].position_not_expanded)) { overlap = true; } } } } if (!overlap) { mGUI_containers[j].position_not_expanded = mCurrentlyDragged; mGUI_containers[j].position.x = mGUI_containers[j].position_not_expanded.x; mGUI_containers[j].position.y = mGUI_containers[j].position_not_expanded.y; } } else if( Event.current.type == EventType.MouseUp ) { mCurrentlyDragging = -1; } } } // Display markers for NPC game objects. for (int iw = 0; iw < mSimulationController.numberOfnpcs; iw++) { if (mSimulationController.npcs[iw].active) { Vector3 worldPoint = mSimulationController.npcs[iw].transform.position; if (Vector3.Dot(Camera.main.transform.forward, worldPoint-Camera.main.transform.position) >= 0){ Vector3 screenPoint = GetComponent<Camera>().WorldToScreenPoint(worldPoint); Rect lTmpRect = new Rect(0, 0, Screen.width, Screen.height); if (lTmpRect.Contains(screenPoint)) { bool overlap = false; Rect lLabelAreaLogo = new Rect(screenPoint.x, Screen.height-screenPoint.y, 20, 20); Rect lLabelAreaTag = new Rect(screenPoint.x+20, Screen.height-screenPoint.y, 100, 20); for (int l = 1; l < 6; l++) { if (mGUI_containers[l].expanded) { if (RectsOverap(lLabelAreaLogo, mGUI_containers[l].position) || RectsOverap(lLabelAreaTag, mGUI_containers[l].position)) { overlap = true; } } else { if (RectsOverap(lLabelAreaLogo, mGUI_containers[l].position_not_expanded)|| RectsOverap(lLabelAreaTag, mGUI_containers[l].position_not_expanded)) { overlap = true; } } } if (!overlap) { GUI.Box(lLabelAreaLogo, mNPCmarkers[iw], GUI.skin.button); GUI.Label(lLabelAreaTag, mSimulationController.npcs[iw].tag, GUI.skin.label);//, mNPCmarkers[iw])); } } } } } // React to changed simulation type. if (mCurrentSimulationTypeChanged) { // Update the AI behavior dropdown list on the basis of the new simulation type switch (mSimulationController.currentSimulationCategory) { case SIMULATION.KINEMATIC_MOVEMENT: mSelectionStringsAIBehavior = new string[System.Enum.GetValues( typeof( KINEMATIC_MOVEMENT ) ).Length]; for (int ic = 0; ic < mSelectionStringsAIBehavior.Length; ic++) { mSelectionStringsAIBehavior[ic] = ((KINEMATIC_MOVEMENT) ic).ToString(); } break; case SIMULATION.STEERING_BEHAVIOR: mSelectionStringsAIBehavior = new string[System.Enum.GetValues( typeof( STEERING_BEHAVIOR ) ).Length]; for (int iv = 0; iv < mSelectionStringsAIBehavior.Length; iv++) { mSelectionStringsAIBehavior[iv] = ((STEERING_BEHAVIOR) iv).ToString(); } break; } // Set situation to "no changes have occurred". mCurrentSimulationTypeChanged = false; } // React to changed AI behavior if (mCurrentAIBehaviourChanged == true) { // Set current action of each NPC to the selected AI action. for (int im = 0; im < mSimulationController.numberOfnpcs; im++) { GameObject tmpNPC = GameObject.FindWithTag("theNPC" + im); if (tmpNPC != null) { mNPCController = tmpNPC.GetComponent<cNPCController>(); mSimulationController.currentSimulationSpeed = (int) mCurrentSpeed; } } // Set situation to "no changes have occurred". mCurrentAIBehaviourChanged = false; } }
/// <summary> /// Actions carried out when this instance is started. /// </summary> void Start() { // Find the simulation controller script. mSimulationController = GameObject.FindWithTag("MainCamera").GetComponent<cSimulationController>(); // Find out the number of NPCs mGUI_NumberOfNPCs = mSimulationController.numberOfnpcs.ToString(); mNumberOfNPCs = mSimulationController.numberOfnpcs; mNewNumberOfNPCs = mNumberOfNPCs; // Set up individual NPC game objects' behavior markers mIndividualAIBehaviourMarkers = new int[mNumberOfNPCs]; for (int i = 0; i < mNumberOfNPCs; i++) { mIndividualAIBehaviourMarkers[i] = 0; } // Set up color picker data. mColorPickerVisible = new bool[mNumberOfNPCs]; for (int i = 0; i < mNumberOfNPCs; i++) { mColorPickerVisible[i] = false; } // Set up markers for NPC game objects. mNPCmarkers = new Texture2D[mNumberOfNPCs]; for (int i = 0; i < mNPCmarkers.Length; i++) { mNPCmarkers[i] = new Texture2D(24, 24); for (int j = 0; j < 24; j++) for (int k = 0; k < 24; k++) mNPCmarkers[i].SetPixel(j, k, new Color(1.0f/i, 0.0f, 0.0f, 1.0f)); mNPCmarkers[i].Apply(); } // Create arrays for mini camera sizes and views. mSelectionGridIntCamSizes = new int[3]; mSelectionGridIntCamViews = new int[4]; // Set initial values for speed slider. mSpeedSliderValue = 15.0f; mSimulationController.currentSimulationSpeed = (int) mSpeedSliderValue; mCurrentSpeed = mSpeedSliderValue; // Set initial values for current simulation type and AI behaviour. mSimulationController.currentAIBehavior = (int) KINEMATIC_MOVEMENT.Do_Nothing; mSimulationController.currentSimulationCategory = SIMULATION.KINEMATIC_MOVEMENT; // Acquire content for the Simulation Type dropdown list. mSelectionStringsSimulationType = new string[System.Enum.GetValues( typeof( SIMULATION ) ).Length]; for (int i = 0; i < mSelectionStringsSimulationType.Length; i++) { mSelectionStringsSimulationType[i] = ((SIMULATION) i).ToString(); } // Acquire content for the AI behavior dropdown list based on the current simulation type. switch (mSimulationController.currentSimulationCategory) { case SIMULATION.KINEMATIC_MOVEMENT: mSelectionStringsAIBehavior = new string[System.Enum.GetValues( typeof( KINEMATIC_MOVEMENT ) ).Length]; for (int i = 0; i < mSelectionStringsAIBehavior.Length; i++) { mSelectionStringsAIBehavior[i] = ((KINEMATIC_MOVEMENT) i).ToString(); } break; case SIMULATION.STEERING_BEHAVIOR: mSelectionStringsAIBehavior = new string[System.Enum.GetValues( typeof( STEERING_BEHAVIOR ) ).Length]; for (int i = 0; i < mSelectionStringsAIBehavior.Length; i++) { mSelectionStringsAIBehavior[i] = ((STEERING_BEHAVIOR) i).ToString(); } break; } // Set initial situation to "no changes have occurred". mCurrentAIBehaviourChanged = false; mCurrentSimulationTypeChanged = false; // Set up GUI containers data. for (int i = 0; i < 4; i++) { mGUI_containers[i].name = "Camera" + (i+1); mGUI_containers[i].position = new Rect (0.78f*Screen.width, (0.01f + (i-1) * 0.33f)*Screen.height, 126, 0.30f*Screen.height); mGUI_containers[i].position_not_expanded = new Rect (0.78f*Screen.width, (0.01f + (i-1) * 0.33f)*Screen.height, 126, 32); mGUI_containers[i].expanded = true; mGUI_containers[i].target = i+1; } mGUI_containers[0].target = 1; mGUI_containers[1].target = 2; mGUI_containers[2].target = 3; mGUI_containers[3].target = 4; mGUI_containers[4].name = "Simulation settings"; mGUI_containers[4].position = new Rect (0.01f*Screen.width,0.02f*Screen.height, 0.13f*Screen.width,0.60f*Screen.height); mGUI_containers[4].position_not_expanded = new Rect (0.01f*Screen.width,0.02f*Screen.height, 0.13f*Screen.width,32); mGUI_containers[4].expanded = true; mGUI_containers[4].target = 1; mGUI_containers[5].name = "Individual NPC settings"; mGUI_containers[5].position = new Rect (0.15f*Screen.width,0.02f*Screen.height, 0.60f*Screen.width,mNumberOfNPCs*0.06f*Screen.height); mGUI_containers[5].position_not_expanded = new Rect (0.15f*Screen.width,0.02f*Screen.height, 0.60f*Screen.width, 32); mGUI_containers[5].expanded = true; mGUI_containers[5].target = 1; }
/// <summary> /// Update called in every frame. /// </summary> void Update() { // Find the simulation controller script and extract Boid data. mSimulationController = GameObject.FindWithTag("MainCamera").GetComponent<cSimulationController>(); mNumberOfBoids = mSimulationController.numberOfnpcs; mBoids = mSimulationController.npcs; // For each memebr of the flock... for (int i = 0; i < mNumberOfBoids; i++) { // Start calculating the flocking factors from reset values. ResetFlockingFactors(); // For each member preceding the current one... for (int j = i+1; j < mNumberOfBoids; j++) { // If the members are near enough of each other, update the flocking factors and neighbour count. if (AreNeighbours(mBoids[i], mBoids[j])) { NeighboursCount++; CumulateCohesion(j); CumulateAlignment(j); CumulateSeparation(j); } } // For each member succeeding the current one... for (int j = 0; j < i; j++) { // If the member are near enough of each other, update the flocking factors and neighbour count if (AreNeighbours(mBoids[i], mBoids[j])) { NeighboursCount++; CumulateCohesion(j); CumulateAlignment(j); CumulateSeparation(j); } } // resolve the final flocking factors. ResolveCohesion(i); ResolveAlignment(i); ResolveSeparation(i); // Set suggestive directional force and forward direction of the current member. Vector3 lNewDirectionalForce = Vector3.zero; // Calculate new directional force to apply based on cohesion and separation. mCohesionFactor -= mBoids[i].transform.position; mSeparationFactor -= mBoids[i].transform.position; cNPCController lTmpScript = mBoids[i].GetComponent<cNPCController>(); if (mCohesionFactor != Vector3.zero || mSeparationFactor != Vector3.zero) { lNewDirectionalForce = ((lTmpScript.mFlockingData.mCohesionWeight/100.0f*mCohesionFactor) + (lTmpScript.mFlockingData.mSeparationWeight/100.0f*mSeparationFactor))/2;// + (mSeparationFactor); } // Set new forward direction to apply based on the alignment factor. Vector3 lNewForwardDirection = mAlignmentFactor; // If there are leaders set for a flock to follow ... if (mSimulationController.flockingLeadersCount > 0) { bool LeaderFound = false; int j = 0; // Find a leader ... while (!LeaderFound && j < mNumberOfBoids) { if (i != j) { mNPCController = GameObject.FindWithTag("theNPC" + j).GetComponent<cNPCController>(); if (mNPCController.mFlockingData.mRole == FLOCK_ROLE.leader) { // If the members are near enough of each other, update the flocking factors and neighbour count. if (AreNeighbours(mBoids[i], mBoids[j])) { LeaderFound = true; lNewDirectionalForce += (mNPCController.mKinematicData.mPosition[mNPCController.mKinematicData.mPosition.Count-1]-mBoids[i].transform.position)*10; } } } j++; } } // Update boid velocity and facing lTmpScript.mFlockingData.mBoidVelocity = lNewDirectionalForce; lTmpScript.mFlockingData.mBoidFacing = lNewForwardDirection; NeighboursCount = 0; } }
/// <summary> /// Actions carried out when this instance is started. /// </summary> void Start() { // Find the simulation controller and extract Boid data. mSimulationController = GameObject.FindWithTag("MainCamera").GetComponent<cSimulationController>(); mNumberOfBoids = mSimulationController.numberOfnpcs; mBoids = mSimulationController.npcs; }