private AgentDirection CalculateAgentDirection(Vector3 selfPosition, Vector3 rayDirection, float sightFactor = 1.0f) { if (debug) { Debug.DrawRay(selfPosition, rayDirection * sight, visionColor); } //Calculate a random utility to initiate the AgentDirection. float utility = Random.Range(Mathf.Min(randomDirectionValue.x, randomDirectionValue.y), Mathf.Max(randomDirectionValue.x, randomDirectionValue.y)); //Create an AgentDirection struct with a random utility value [utility]. Ignores y component. AgentDirection direction = new AgentDirection(new Vector3(rayDirection.x, 0.0f, rayDirection.z), utility); //Raycast into the rayDirection to check if something can be seen in that direction. //The sightFactor is a variable that increases / decreases the size of the ray. //For now, the sightFactor is only used to control the long sight in front of the agent. if (Physics.Raycast(selfPosition, rayDirection, out RaycastHit raycastHit, sight * sightFactor)) { if (debug) { Debug.DrawLine(selfPosition, raycastHit.point, foundColor); } //Calculate the normalized distance from the agent to the intersected object. //Closer objects will have distancedNormalized close to 0, and further objects will have it close to 1. float distanceNormalized = (raycastHit.distance / (sight * sightFactor)); //Inverts the distanceNormalized. Closer objects will tend to 1, while further objects will tend to 0. //Thus, closer objects will have a higher value. float distanceIndex = 1.0f - distanceNormalized; //Calculate the utility of the found object according to its type. switch (raycastHit.collider.gameObject.tag) { //All formulas are the same. Only the weights change. case "Box": utility = distanceIndex * distanceFactor + boxWeight; break; case "x4Box": utility = distanceIndex * x4distanceFactor + x4boxWeight; break; case "x16Box": utility = distanceIndex * x16distanceFactor + x16boxWeight; break; case "Boat": utility = distanceIndex * boatDistanceFactor + boatWeight; break; case "Wall": utility = distanceIndex * wallDistanceFactor + wallWeight; break; } } direction.utility = utility; return(direction); }
public void SetDecision(int index, Decision decide) { for (int i = 0; i < Data.AgentsCount; ++i) { AgentDirection dir = DirectionExtensions.CastPointToDir(decide.Agents[i]); viewModel.Players[index].AgentViewModels[i].Data.AgentDirection = dir; viewModel.Players[index].AgentViewModels[i].Data.State = AgentState.Move; } }
public void SetDirection(AgentDirection direction) { if (this.Direction != direction) { var scale = this.transform.localScale; this.transform.localScale = new Vector3(-scale.x, scale.y, scale.z); this.Direction = direction; } }
/// <summary> /// Calculate the best direction to move using the Agent properties. /// The agent shoots a ray in a area on front of itself and calculates the utility of each one of them based on what /// it did intersect or using a random value (uses a Random from [randomDirectionValue.x, randomDirectionValue.y]). /// </summary> private void Act() { //Clear the visible objetcs with a small delay, so that the objects in actual range dont get ignored because the raycast moved if (actIteration >= 60) { visibleObjects.Clear(); actIteration = 0; //Reset environment factor along with the visible objects speedEnvironmentWeight = 1f; pullEnvironmentWeight = 1f; multiplierEnvironmentWeight = 1f; } Transform selfTransform = transform; Vector3 forward = selfTransform.forward; //Ignores the y component to avoid flying/sinking Agents. forward.y = 0.0f; forward.Normalize(); Vector3 selfPosition = selfTransform.position; //Initiate the rayDirection on the opposite side of the spectrum. Vector3 rayDirection = Quaternion.Euler(0, -1.0f * steps * (rayRadius / 2.0f), 0) * forward; //List of AgentDirection (direction + utility) for all the directions. List <AgentDirection> directions = new List <AgentDirection>(); for (int i = 0; i <= rayRadius; i++) { //Add the new calculatedAgentDirection looking at the rayDirection. directions.Add(CalculateAgentDirection(selfPosition, rayDirection)); //Rotate the rayDirection by _steps every iteration through the entire rayRadius. rayDirection = Quaternion.Euler(0, steps, 0) * rayDirection; } //Adds an extra direction for the front view with a extra range. directions.Add(CalculateAgentDirection(selfPosition, forward, 1.5f)); directions.Sort(); //There is a (100 - _maxUtilityChoiceChance) chance of using the second best option instead of the highest one. Should help into ambiguous situation. AgentDirection highestAgentDirection = directions[Random.Range(0.0f, 100.0f) <= _maxUtilityChoiceChance ? 0 : 1]; //Rotate towards to direction. The factor of 0.1 helps to create a "rotation" animation instead of automatically rotates towards the target. transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(highestAgentDirection.Direction), 0.1f); //Sets the velocity using the chosen direction _rigidbody.velocity = highestAgentDirection.Direction * movingSpeed * speedMultiplier; actIteration++; if (debug) { Debug.DrawRay(selfPosition, highestAgentDirection.Direction * (sight * 1.5f), directionColor); } }
/// <summary> /// Notices that this method is an "inverse" sorting. It makes the higher values on top of the Sort, instead of /// the smaller values. For the smaller values, the return line would be utility.CompareTo(otherAgent.utility). /// </summary> /// <param name="obj"></param> /// <returns></returns> public int CompareTo(object obj) { if (obj == null) { return(1); } AgentDirection otherAgent = (AgentDirection)obj; return(otherAgent.utility.CompareTo(utility)); }
protected override bool Trigger() { if (this.Agent.DashStatus.IsDashing) { return(false); } if (Input.GetAxis("Horizontal") < -0.1) { this.direction = AgentDirection.Left; return(true); } if (Input.GetAxis("Horizontal") > 0.1) { this.direction = AgentDirection.Right; return(true); } return(false); }
private void moveTowards() { // Move the agent towards the node Vector3 update = Vector3.MoveTowards(lastPosition, target.WorldPosition, moveSpeed * Time.deltaTime); // Get the movement vector only Vector3 temp = update - lastPosition; // Make sure the vector is not zero if (temp.sqrMagnitude != 0) { // Check if the movement is up or down if (temp.y <= 0.002f) { // Moving downwards - Default to forward where possible direction = AgentDirection.Forward; } else { // Moving upwards direction = AgentDirection.Backward; } if (temp.x > 0) { // Moiving right direction |= AgentDirection.Right; } else if (temp.x < 0) { // Moving left direction |= AgentDirection.Left; } } // Set the moving flag isMoving = (update != transform.position); // Update the position transform.position = update; lastPosition = transform.position; }
private AgentDirection CalculateAgentDirection(Vector3 selfPosition, Vector3 rayDirection, float sightFactor = 1.0f) { if (debug) { Debug.DrawRay(selfPosition, rayDirection * sight, visionColor); } //Calculate a random utility to initiate the AgentDirection. float utility = Random.Range(Mathf.Min(randomDirectionValue.x, randomDirectionValue.y), Mathf.Max(randomDirectionValue.x, randomDirectionValue.y)); //Create an AgentDirection struct with a random utility value [utility]. Ignores y component. AgentDirection direction = new AgentDirection(new Vector3(rayDirection.x, 0.0f, rayDirection.z), utility); //Raycast into the rayDirection to check if something can be seen in that direction. //The sightFactor is a variable that increases / decreases the size of the ray. //For now, the sightFactor is only used to control the long sight in front of the agent. if (Physics.Raycast(selfPosition, rayDirection, out RaycastHit raycastHit, sight * sightFactor)) { if (debug) { Debug.DrawLine(selfPosition, raycastHit.point, foundColor); } //Calculate the normalized distance from the agent to the intersected object. //Closer objects will have distancedNormalized close to 0, and further objects will have it close to 1. float distanceNormalized = (raycastHit.distance / (sight * sightFactor)); //Inverts the distanceNormalized. Closer objects will tend to 1, while further objects will tend to 0. //Thus, closer objects will have a higher value. float distanceIndex = 1.0f - distanceNormalized; GameObject visibleObject = raycastHit.collider.gameObject; //Calculate the utility of the found object according to its type. switch (visibleObject.tag) { case "Box": utility = distanceIndex * boxDistanceFactor + boxWeight; break; case "Boat": utility = distanceIndex * boatDistanceFactor + boatWeight; break; case "Enemy": utility = distanceIndex * enemyDistanceFactor + enemyWeight; break; case "Speed": if (!abled) { break; } utility = distanceIndex * speedDistanceFactor + speedWeight * speedEnvironmentWeight * speedActiveFactor; break; case "Pull": if (!abled) { break; } utility = distanceIndex * pullDistanceFactor + pullWeight * pullEnvironmentWeight; break; case "Multiplier": if (!abled) { break; } utility = distanceIndex * multiplierDistanceFactor + multiplierWeight * multiplierEnvironmentWeight * multiplierActiveFactor; break; } //Add or update the object in the dictionary. if (visibleObjects.ContainsKey(visibleObject)) { visibleObjects[visibleObject] = utility; } else { visibleObjects.Add(visibleObject, utility); //Increase the probability of the agent to pick up a powerup, depending on how many objects are around. speedEnvironmentWeight += speedEnvironmentFactor; pullEnvironmentWeight += pullEnvironmentFactor; multiplierEnvironmentWeight += multiplierEnvironmentFactor; } } direction.utility = utility; return(direction); }