/// <summary> /// Assign new Behaviour model to Agent. /// </summary> /// <param name="behaviour"></param> public void SetBehaviour(EliotBehaviour behaviour) { try{ _behaviour = behaviour; _behaviourCore = CoresPool.GetCore(_behaviour, gameObject); }catch (Exception) { /**/ } }
/// <summary> /// Make an Agent wield the Item. May lead to changes in Agent's cofiguration. /// </summary> /// <param name="agent"></param> public void Wield(Agent agent) { if (_currentInventory.WieldedItem) { _currentInventory.WieldedItem.Unwield(agent); } _currentInventory.WieldedItem = this; if (_addSkills.Length > 0) { foreach (var skill in _addSkills) { agent.AddSkill(skill); } } if (_newBehaviour) { _previousBehaviour = agent.GetBehaviour; agent.SetBehaviour(_newBehaviour); } if (_newGraphics) { agent.ReplaceGraphics(_newGraphics); } if (_wieldSound) { agent.GetAudioSource().clip = _wieldSound; agent.GetAudioSource().Play(); } }
/// <summary> /// Make an Agent wield the Item. May lead to changes in Agent's cofiguration. /// </summary> /// <param name="agent"></param> public void Wield(Agent agent) { if (_currentInventory.WieldedItem) { _currentInventory.WieldedItem.Unwield(agent); } _currentInventory.WieldedItem = this; if (_addSkills.Length > 0) { foreach (var skill in _addSkills) { agent.AddSkill(skill); } } if (_newBehaviour) { _previousBehaviour = agent.GetBehaviour; agent.SetBehaviour(_newBehaviour); } if (_newGraphics) { agent.ReplaceGraphics(_newGraphics); } if (_wieldSound) { agent.GetAudioSource().clip = _wieldSound; agent.GetAudioSource().Play(); } //Use if (!_skill) { return; } //agent.AddEffect(_skill, agent); _amount--; if (_amount > 0) { return; } //Get dropped function if (!_isInInventory) { return; } gameObject.SetActive(true); _isInInventory = false; _currentInventory = null; Destroy(gameObject); //Unwield(agent); }
/// <summary> /// Create json string from Behaviour. /// </summary> /// <param name="core"></param> public static void ToJson(this EliotBehaviour core) { var res = Object(null, true, Field("version", 1.2F), Array("nodes", (from node in core.Nodes select node.ToJson()).ToList()), Array("transitions", (from trans in core.Transitions select trans.ToJson()).ToList())); core.Json = res; }
/// <summary> /// Read the version of the Behaviour and return an updated version. /// </summary> /// <param name="behaviour"></param> public static void UpdateBehaviour(this EliotBehaviour behaviour) { behaviour.Json = UpdateJson(behaviour.Json); }
/// <summary> /// Draw all the window graphics. /// </summary> private void OnGUI() { //GUI.DrawTexture(new Rect(0,0,350,100), _unitFactoryLogo); //Space(15); Tip("Create new Agent here giving some general idea of his \nparameters." + "You can always adjust them in the inspector \nof already created Agent."); Space(); _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition); Header("General"); _name = EditorGUILayout.TextField("Agent's name: ", _name); _team = EditorGUILayout.TextField("Team: ", _team); _weight = EditorGUILayout.FloatField("Weight: ", _weight); Space(2); Header("Perception"); _seeDistance = EditorGUILayout.FloatField("Perception range:", _seeDistance); _seeFOV = EditorGUILayout.FloatField("Field of view: ", _seeFOV); _seeResolution = (UnitFactoryOptions)EditorGUILayout.EnumPopup("Accuracy of perception: ", _seeResolution); _memoryDuration = EditorGUILayout.IntField("Memory duration: ", _memoryDuration); Space(2); Header("Motion"); _motionEngine = (MotionEngine)EditorGUILayout.EnumPopup("Motion engine: ", _motionEngine); //_canMove = EditorGUILayout.Toggle("Should it move?", _canMove); _moveSpeed = (UnitFactoryOptions)EditorGUILayout.EnumPopup("Move speed: ", _moveSpeed); _canRun = EditorGUILayout.Toggle("Can it run?", _canRun); _canDodge = EditorGUILayout.Toggle("Can it dodge?", _canDodge); Space(2); Header("Resources"); _isMortal = EditorGUILayout.Toggle("Is it mortal?", _isMortal); if (_isMortal) { _maxHealth = EditorGUILayout.IntField("Health capacity: ", _maxHealth); } _useEnergy = EditorGUILayout.Toggle("Does it use energy?", _useEnergy); if (_useEnergy) { _maxEnergy = EditorGUILayout.IntField("Energy capacity: ", _maxEnergy); } Space(2); Header("Other"); _graphics = (GameObject)EditorGUILayout.ObjectField("Graphics: ", _graphics, typeof(GameObject), false); _ragdoll = (GameObject)EditorGUILayout.ObjectField("Ragdoll: ", _ragdoll, typeof(GameObject), false); _behaviour = (EliotBehaviour)EditorGUILayout.ObjectField("Behaviour: ", _behaviour, typeof(EliotBehaviour), false); _waypoints = (WaypointsGroup)EditorGUILayout.ObjectField("Waypoints: ", _waypoints, typeof(WaypointsGroup), true); Space(2); Header("Skills"); if (_skills.Count > 0) { for (var i = _skills.Count - 1; i >= 0; i--) { EditorGUILayout.BeginHorizontal(); _skills[i] = (Skill)EditorGUILayout.ObjectField(_skills[i], typeof(Skill), false); if (GUILayout.Button("Remove")) { _skills.RemoveAt(i); } EditorGUILayout.EndHorizontal(); } } if (GUILayout.Button("Add skill")) { _skills.Add(null); } EditorGUILayout.Space(); if (GUILayout.Button("Create")) { //Resources var resources = Resources.CreateResources(_isMortal, _maxHealth, _useEnergy, _maxEnergy); //Memory var memory = Memory.CreateMemory(_memoryDuration); //See var resolution = 0; switch (_seeResolution) { case UnitFactoryOptions.Low: resolution = 7; break; case UnitFactoryOptions.Medium: resolution = 15; break; case UnitFactoryOptions.High: resolution = 35; break; } var perception = Perception.CreatePerception(_seeDistance, _seeFOV, resolution); //Move var speed = 0f; switch (_moveSpeed) { case UnitFactoryOptions.Low: speed = 1.5f; break; case UnitFactoryOptions.Medium: speed = 3f; break; case UnitFactoryOptions.High: speed = 5f; break; } var motion = Motion.CreateMotion(_motionEngine, speed, _canRun, _canDodge); motion.Weight = _weight; //Death var death = Death.CreateDeath(_ragdoll); //Settings var stats = Settings.CreateSettings(); var newAgent = Agent.CreateAgent(_name, resources, memory, perception, motion, death, stats, _skills, _graphics); newAgent.Behaviour = _behaviour; newAgent.GetComponent <Unit>().Team = _team; newAgent.Waypoints = _waypoints; newAgent.transform.position = SceneView.lastActiveSceneView.pivot; Selection.activeObject = newAgent; } EditorGUILayout.EndScrollView(); }
/// <summary> /// Create all the Behaviour objects from its json string. /// </summary> /// <param name="behaviour"></param> public static void Serialize(this EliotBehaviour behaviour) { behaviour.Nodes = new List <Node>(); BehaviourEditorWindow.Nodes = new List <Node>(); var jObj = new JsonObject(behaviour.Json); var jNodes = jObj["nodes"].Objects; if (jNodes == null) { behaviour.Nodes = new List <Node>(); behaviour.Transitions = new List <NodesTransition>(); BehaviourEditorWindow.Nodes = behaviour.Nodes; BehaviourEditorWindow.Clear(null); } else { if (jNodes.Count > 0) { foreach (var node in jNodes) { behaviour.Nodes.Add(BehaviourEditorWindow.TemplateNode(((JsonObject)node)["type"].String).Serialize((JsonObject)node)); } } behaviour.Transitions = new List <NodesTransition>(); var jTransitions = jObj["transitions"].Objects; foreach (var trans in jTransitions) { var transition = (JsonObject)trans; if (transition["startID"] == null) { break; } var startId = transition["startID"].Int; var endId = transition["endID"].Int; var isNeg = transition["type"].String.Equals("negative"); int minRate, maxRate; float minCooldown, maxCooldown; bool terminate; try { minRate = transition["minRate"].Int; maxRate = transition["maxRate"].Int; minCooldown = transition["minCooldown"].Float; maxCooldown = transition["maxCooldown"].Float; terminate = transition["terminate"].Bool; } catch (Exception) { minRate = 1; maxRate = 1; minCooldown = 0f; maxCooldown = 0f; terminate = false; } var color = BehaviourEditorWindow.NeutralColor; var tColor = transition["color"]; if (tColor != null) { var r = transition["color"]["r"].Float; var g = transition["color"]["g"].Float; var b = transition["color"]["b"].Float; var a = Mathf.Clamp(1f / (maxRate * 0.2f) + 0.2f, 0.5f, 2f); color = new Color(r, g, b, a); } var t = BehaviourEditorWindow.TemplateTransition(); t.Start = behaviour.Nodes[startId]; t.End = behaviour.Nodes[endId]; t.IsNegative = isNeg; t.MinRate = minRate; t.MaxRate = maxRate; t.MinCooldown = minCooldown; t.MaxCooldown = maxCooldown; t.Terminate = terminate; t.Color = color; behaviour.Nodes[startId].Transitions.Add(t); behaviour.Transitions.Add(t); } BehaviourEditorWindow.Nodes = behaviour.Nodes; } }
/// <summary> /// Decipher the file and create methods and relations between them using reflection. /// </summary> /// <param name="behaviour"></param> /// <param name="gameObject"></param> /// <returns></returns> public static BehaviourCore GetCore(EliotBehaviour behaviour, GameObject gameObject) { var core = new BehaviourCore(); behaviour.Json = BehaviourVersionManager.UpdateJson(behaviour.Json); // See if there are any nodes in file. var jObj = new JsonObject(behaviour.Json); var jNodes = jObj["nodes"].Objects; if (jNodes == null) { return(null); } Entry entry = null; var particles = new List <EliotComponent>(); // If there are, create Behaviour Components from each piece of data. if (jNodes.Count > 0) { foreach (var node in jNodes) { var nodeObj = (JsonObject)node; var type = nodeObj["type"].String; switch (type) { case "Entry": { entry = new Entry(nodeObj["ID"].String); particles.Add(entry); break; } case "Invoker": { var actionGroup = nodeObj["actionGroup"].ActionGroup; string[] funcNames; string functionName; int funcIndex = -1; var execute = true; if (actionGroup == ActionGroup.Skill) { funcIndex = 0; funcNames = new[] { nodeObj["functionID"].String }; functionName = nodeObj["functionName"].String; if (nodeObj["executeSkill"] != null) { execute = nodeObj["executeSkill"].Bool; } } else if (actionGroup == ActionGroup.Inventory) { //funcIndex = nodeObj["functionID"].Int; funcNames = AgentFunctions.GetFunctions <InventoryActionInterface>(); functionName = nodeObj["functionName"].String; } else { //funcIndex = nodeObj["functionID"].Int; funcNames = AgentFunctions.GetFunctions <MotionActionInterface>(); functionName = nodeObj["functionName"].String; } //_____________________________________CAUTION WORK IN PROGRESS________________________ //Array.Sort(funcNames, StringComparer.InvariantCulture); for (var i = 0; i < funcNames.Length; i++) { if (funcNames[i] == functionName) { funcIndex = i; } } if (funcIndex == -1) { funcIndex = nodeObj["functionID"].Int; } //_____________________________________________________________________________________ var inv = new Invoker(AgentFunctions.CreateAction(funcNames[funcIndex], gameObject, actionGroup, execute), nodeObj["ID"].String); particles.Add(inv); break; } case "Observer": { var funcIndex = nodeObj["functionID"].Int; var conditionGroup = nodeObj["conditionGroup"].ConditionGroup; var funcNames = AgentFunctions.GetConditionStrings(conditionGroup); var functionName = nodeObj["functionName"].String; var obs = new Observer(AgentFunctions.CreateCondition(functionName, gameObject, conditionGroup, nodeObj["ID"].Int), nodeObj["ID"].String); particles.Add(obs); break; } case "Loop": { var funcIndex = nodeObj["functionID"].Int; var conditionGroup = nodeObj["conditionGroup"].ConditionGroup; var funcNames = AgentFunctions.GetConditionStrings(conditionGroup); var functionName = nodeObj["functionName"].String; var reverse = nodeObj["reverse"] != null && nodeObj["reverse"].Bool; var loop = new Loop(core, reverse, AgentFunctions.CreateCondition(functionName, gameObject, conditionGroup, nodeObj["ID"].Int), nodeObj["ID"].String); particles.Add(loop); break; } } } } // Now we need to connect the Components. var jTransitions = jObj["transitions"].Objects; foreach (var trans in jTransitions) { // Retrieve the needed information from data. var transition = (JsonObject)trans; var startId = transition["startID"].String; var endId = transition["endID"].String; var isNeg = transition["type"].String.Equals("negative"); int minRate, maxRate; float minCooldown, maxCooldown; bool terminate; try { minRate = transition["minRate"].Int; maxRate = transition["maxRate"].Int; minCooldown = transition["minCooldown"].Float; maxCooldown = transition["maxCooldown"].Float; terminate = transition["terminate"].Bool; } catch (Exception) { minRate = 1; maxRate = 1; minCooldown = 0f; maxCooldown = 0f; terminate = false; } // Connect proper Components by their IDs. try { var type = ComponentTypeById(particles, startId); if (type == "Observer") { if (isNeg) { ((Observer)particles.FirstOrDefault(particle => particle.Id == startId)) .ConnectWith_Else(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } else { particles.FirstOrDefault(particle => particle.Id == startId) .ConnectWith(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } } else if (type == "Loop") { if (isNeg) { ((Loop)particles.FirstOrDefault(particle => particle.Id == startId)) .ConnectWith_End(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } else { particles.FirstOrDefault(particle => particle.Id == startId) .ConnectWith(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } } else { particles.FirstOrDefault(particle => particle.Id == startId) .ConnectWith(particles.FirstOrDefault(particle => particle.Id == endId), minRate, maxRate, minCooldown, maxCooldown, terminate); } } catch (NullReferenceException) { Debug.Log("Something is wrong with data."); } } // Set the Entry. core.Entry = entry; return(core); }