0
\$\begingroup\$

I am typing a code using C# in unity for game called Sea Gauntlet. In this game, there is a hero ship which I am suppose to control to do certain tasks. Along with that there is whirlpools, drones designed to destroy the ship and there are shield and hull power ups to survive in this game. It is surrounded by lake.

In this task, I am trying to avoid the whirlpool while collecting one shield and one hull power up. Here the AvoidWhirlpool passes a parameter Position2 Whirlpool.

This is just one whirlpool so even though I try to loop through all the whirlpools I am actually only looking at the same whirlpool many times. Any suggestion as to how to fix the problem? I have done the coding this far.

 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;

 public class AI : MonoBehaviour
 {
    public float vectornorth, vectoreast, ForwardThrust, RotationSpeed;
public float endDistance = 40f;
public float pressureScale = 0.1f;
public float rateScale = 4.2f;

public PID.PID_Params forwardThrustPIDParms;

public Position2[] waypoints = new Position2[5];
public int waypointIndex = 0;

public Position2[] MoveAwayWhirlpool = new Position2[5];
public int MoveAwayWhirlpoolIndex = 0;

// Used to initialise at the start of a Game Level or Task
public void StartTaskOrLevel()  // This is called at the start of each Task or game level
{
    forwardThrust = 0f;       // Initialise motion to zero
    rotationSpeed = 0f;

    forwardThrustPIDParms = pid.PIDParametersSet(1, 0, 0, -heroStatus.maxForwardThrust, heroStatus.maxForwardThrust, 0, 0);

    resetDataRunTime = true;
    logDataString = "X,Y";
    logData = true;

    waypoints[0].east = 100;
    waypoints[0].north = 100;
    waypoints[1].east = 200;
    waypoints[1].north = -100;
    waypoints[2].east = 300;
    waypoints[2].north = -200;
    waypoints[3].east = 100;
    waypoints[3].north = -100;
    waypoints[4].east = 250;
    waypoints[4].north = -100;
}


// Used to update Hero during a task or Game Level.
public void TaskOrLevelUpdate() // This is called 50 times per second during a Task or game level but not when a menu is displayed.
{

    if (heroStatus.task)
    {                               // Do task
        switch (heroStatus.level)
        {
            case 1:
                Task1();
                break;
            case 2:
                Task2();
                break;
                //case 3:
                //    Task3();
                //    break;
                //case 10:
                //    Task10();
                //    break;
        }
    }
    else
    {                              // Do Game

    }
}

// Used to close anything at the end of a Game Level or Task
public void EndTaskOrLevel()  // This is called at the end of each Task or game level
{
    logData = false;
}

public void Task1()
{
    float vectornorth, vectoreast, distToWhirlpool, stopDisPoint;
    float requiredVel;

    vectornorth = whirlpools[0].north - heroStatus.position.north;
    vectoreast = whirlpools[0].east - heroStatus.position.east;
    distToWhirlpool = Mathf.Sqrt(Mathf.Pow(vectornorth, 2) + Mathf.Pow(vectoreast, 2)); //calculate the distance from whirlpool
    stopDisPoint = distToWhirlpool - heroStatus.stopDistToWhirlpool;                    // defines about when to stop the ship

    target = whirlpools[0];
    useTarget = true;

    requiredVel = stopDisPoint * rateScale;
    if (stopDisPoint < endDistance)
    {
        requiredVel = stopDisPoint * rateScale;
    }
    else
    {
        requiredVel = heroStatus.maxForwardSpeed / 2f;
    }
    forwardThrustPIDParms = pid.PIDParametersSet(forwardThrustPIDParms, 1, 0, 0, -heroStatus.maxForwardThrust, heroStatus.maxForwardThrust, requiredVel, heroStatus.velocity.forward);
    forwardThrustPIDParms = pid.PIDController(forwardThrustPIDParms);
    forwardThrust = forwardThrustPIDParms.output;

    rotationSpeed = heroStatus.maxRotationSpeed;

} // The code is taken from class code video AI Week 2
public void Task2()
{

    if (shieldPowerups.Length == 0 && hullPowerups.Length == 0)
        return;
    forwardThrust = heroStatus.maxForwardThrust;
    rotationSpeed = heroStatus.maxRotationSpeed;
    if (shieldPowerups.Length != 0 && hullPowerups.Length != 0)
    { // There is both shield and hull power up
        float distShield, distHull;

        distShield = DistBetweenPoints(heroStatus.position, shieldPowerups[0]); // Distance from the shieldpowerup
        distHull = DistBetweenPoints(heroStatus.position, shieldPowerups[0]);   // Distance from hullpowerup
        useTarget = true;
        if (distHull < distShield)
            target = hullPowerups[0];
        else
            target = shieldPowerups[0];
    }
    else
    { // There is one shield or hull power up
        if (hullPowerups.Length != 0)
            target = hullPowerups[0];
        else
            target = shieldPowerups[0];
    } // The code is refered from class code and videos AI Week 3

    target = AvoidWhirlpool(heroStatus.position, whirlpools[0], target);

}

// Name: AvoidWhirlpool
// Input: Position2 - origin, whirlpool, target
// Output: Position2 - target
// Description:
//      Look at area between origin and target. If the whirlpool is
//      within that area, calculate a new target to avoid whirlpool.

public Position2 AvoidWhirlpool(Position2 origin, Position2 whirlpool, Position2 target)
{
    if (whirlpools.Length == 0)
        return target;

    float FinalDistance = 350f;

    // Rotate object 
    Position2 rotTarget;
    Position2 rWhirlpool;

    //Find an angle to rotate through
    float angle = Mathf.Atan2(target.east - origin.east, target.north - origin.north) * 180f / Mathf.PI;

    // Rotate target above.
    rotTarget.east = 0;
    rotTarget.north = DistBetweenPoints(origin, target);

    for (int i = 0; i < whirlpools.Length; i++)
    {
        float distToWhirlpool = DistBetweenPoints(origin, whirlpools[i]);

        // Define original position
        rWhirlpool = whirlpool;
        rWhirlpool.east -= origin.east;
        rWhirlpool.north -= origin.north;

        // Rotate whirlpool in north
        rWhirlpool = RotateAboutUp(rWhirlpool.east, rWhirlpool.north, -angle);

        //Check for obstacle
        if (rWhirlpool.north > 5f && rWhirlpool.north < 300f && rWhirlpool.east > -40f && rWhirlpool.east < 40f)

        {
            //Whirlpool is an obstacle
            if (distToWhirlpool < FinalDistance)
            {
                if (rWhirlpool.east > 0f)
                {
                    // Move target towards left
                    rotTarget.east = -50f;
                    rotTarget.north = distToWhirlpool;
                }
            }
            else
            {
                // Move target towards right
                rotTarget.east = 50f;
                rotTarget.north = distToWhirlpool;
            }
            FinalDistance = distToWhirlpool;  // Save present distance
        }
        else
        {
            // Whirlpool not an obstacle
        }
        target = RotateAboutUp(rotTarget.east, rotTarget.north, angle);
        target.north += origin.north;
        target.east += origin.east;

        return target;
    }
    return target;
}
\$\endgroup\$
1
\$\begingroup\$

Here.

rWhirlpool = whirlpool;

whirlpool is not your current whirlpool, whirlpools[i] is. That's why you look at one and the same whirlpool which comes as a parameter. You don't need that parameter at all.

Also, look at this:

    return target;
} // the brace from for loop

You always return after the first iteration. So you will never process more that one first whirlpool. If you want to iterate through all whirlpools, get rid of this return.

If this function should avoid only one whirlpool, remove the loop from it, and instead call it from inside a loop.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.