Ropes' Adventure
Genre: Singleplayer Adventure
Duration: 7 Weeks
Engine: Unity
Platform: PC
Language: C#
My Role: Scripter/AI Programmer

Ropes' Adventure is a 3rd person adventure-platformer where you play as ropes a young red panda that explores the Monkey Temple in search for his lost grandfather. The game was developed by nine students as a school project where my role was AI Programmer & scripter

Overview


The turtles in rope’s adventure worked as collectables in the game we had both baby turtles that the player has to adventure around the world to find and collect. While the mother turtle was on set location in world and you picked up a baby turtle they would appear following the mother.


Mother Turtle






When i created the mother turtle i wanted her to walk to random position inside a preset zone. The way i did this was i created a sphere that worked as a zone. I attached this to the mothers prefab so the workflow wouldn't get affected and since i didn't want the zone to move with the ai i detached the sphere on start of the game so the mother would only walk inside a radius from where she was placed.

Click Code to Expand

 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Mothership : MonoBehaviour
{
    // Public
    [HideInInspector]
    public NavMeshAgent meshAgent;

    // Private
    GameObject SphereRadius;
    SphereCollider WalkRadius;
    Animator animator;
    DestTrigger TriggerDest;
    Transform triggerTransform;
    Vector3 Destination;
    Vector3 lastpos = Vector3.zero;

    bool hasDestination = false;

    void Start()
    {
        meshAgent = GetComponent<NavMeshAgent>();
        SphereRadius = GetComponentInChildren<AISphereTrigger>().gameObject;
        TriggerDest = SphereRadius.GetComponentInChildren<DestTrigger>();
        triggerTransform = TriggerDest.GetComponent<Transform>();
        animator = GetComponent<Animator>();
        WalkRadius = SphereRadius.GetComponent<SphereCollider>();
        SphereRadius.transform.parent = null;
    }

    // checks if the mother has a destination already or if it should find one
    void Update()
    {
        if (hasDestination == false)
        {
            NewDestination();
        } else {
            float velocity = Vector3.Distance(lastpos, transform.position) / Time.deltaTime;
            lastpos = transform.position;
            animator.SetFloat("Speed", velocity);
        }
    }

    // sets the destination so it could get a new destination again.
    public void UpdateDestination()
    {
        meshAgent.Stop();
        hasDestination = false;
    }

    // finds a postition inside the sphere and sets the world postition of that selected postiton.
    void NewDestination()
    {
        for (int i = 0; i < 30; i++)
        {
            Vector3 randomPoint = SphereRadius.transform.position + Random.insideUnitSphere * WalkRadius.radius;
            NavMeshHit hit;
            if (NavMesh.SamplePosition(randomPoint, out hit, 1.0f, NavMesh.AllAreas))
            {
                Destination = hit.position;
                hasDestination = true;
                break;
            }
        }
        
        //Sets the destination that previous was found insdie the sphere and moves to that
        if (hasDestination)
        {
            triggerTransform.position = Destination;
            meshAgent.SetDestination(Destination);
            meshAgent.Resume();
        }
    }
}


They way i setup the next position was instead of checking the distance between mother to destination on every frame i did a trigger that i move around and when the mother enters the trigger a new destination will be set

Click Code to Expand

 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using UnityEngine;
using System.Collections;

public class DestTrigger : MonoBehaviour {

    [HideInInspector]
    public Mothership mothership;

    // when the mother enters the trigger find a new destination
    void OnTriggerEnter(Collider col){
        if (col.tag == "MotherTurtle")
        {
            mothership.UpdateDestination();
        }
    }

    // Debug
    void OnDrawGizmos()
    {
        Gizmos.color = Color.blue;
        Gizmos.DrawSphere(gameObject.transform.position, gameObject.GetComponent<SphereCollider>().radius);
    }
}


The mother turtle also keeps track on how many baby turtles is lost and adds them to a list for tracking

Click Code to Expand

 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Mothership : MonoBehaviour
{

    [HideInInspector]
    public int totalLostTurtles;

    List<Turtle> lostTurtles = new List<Turtle>();

    // Looks for all object with the script turtles and then check if they are lost. If the turtle is lost then add them to list
    void Awake()
    {
        foreach (Turtle turtle in FindObjectsOfType<Turtle>())
        {
            if (turtle.isLost)
                lostTurtles.Add(turtle);
        }
        totalLostTurtles = lostTurtles.Count;
    }

    public void returnTurtle(Turtle returnedTurtle, TurtleType turtleColour)
    {   
        lostTurtles.Remove(returnedTurtle);

    }
}



Baby Turtle









When the player gets in range with a baby turtle and the turtle haven't been picked up yet. The baby turtle will start jumping and spawn hearths effect to notify the player that the turtle has been found and can be picked up.

Click Code to Expand

 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
using UnityEngine;
using System.Collections;

public class BabyTurtle : MonoBehaviour {
    
    // Public
    [Header("Particles")]
    public ParticleSystem pHearts;

    // Hidden
    [HideInInspector]
    public NavMeshAgent meshAgent;

    // Private

    // References
    Mothership motherShip;
    Turtle turtleScript;
    Animator animator;
    HUD UI;

    // Variables
    int FollowID;
    bool isInTrigger = false;
    bool HasRandomIdle = false;
    bool FollowMother = false;
    bool HasMotherTurtleStop = false;
    bool FirstTimeFound = false;
    bool IsPlayingSound = false;


    // On start of the game gets the referances for each variable and removes the UI from the screen.
    void Start () {
        meshAgent = GetComponent<NavMeshAgent>();
        meshAgent.enabled = false;
        animator = GetComponent<Animator>();
    }



    //Checks if the player is close to the babytrutle and dippending if the turlte has been found or not will give diffrent reaction to the player.
    void OnTriggerEnter(Collider playerCheck)
    {

        if (playerCheck.gameObject.GetComponent<Player>() != null)
        {
            isInTrigger = true;
            pHearts.Play();
            if (FirstTimeFound)
            {
                 meshAgent.Stop();
                 animator.SetBool("beenFound", false);
                 animator.SetBool("Retracted", true);
            } else {
                animator.SetBool("beenFound", true);
            }
        }
    }


    // When the goes away from the babyturtle it then will resume to walk after the player or back to the mother if it has been found
    void OnTriggerExit(Collider playerCheck)
    {
        if (playerCheck.gameObject.GetComponent<Player>() != null)
        {
            isInTrigger = false;
            pHearts.Stop();
            if (motherShip.isMotherInShell == false)
                if (turtleScript.hasGoneOver == false)
                    if (FirstTimeFound)
                    {
                        meshAgent.Resume();
                        animator.SetBool("Retracted", false);
                    } else {
                        animator.SetBool("beenFound", false);
                    }
        }
    }
}


When a baby turtle is pickup then they will be move to the mother turtle and start following her. The Player will also get a notification that they picked up a collectable.

Click Code to Expand

 
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using UnityEngine;
using System.Collections;

public class BabyTurtle : MonoBehaviour {
    
    // Public

    [Header("Particles")]
    public ParticleSystem pHearts;
    public ParticleSystem pCollect;

    // Hidden
    [HideInInspector]
    public NavMeshAgent meshAgent;
    [HideInInspector]
    public bool hasBeenPickup = false;

    // Private

    // References
    Mothership motherShip;

    Transform Follow;
    Interact intract;
    Turtle turtleScript;
    Vector3 lastpos = Vector3.zero;
    Animator animator;
    HUD UI;

    // Variables
    int FollowID;
    bool isInTrigger = false;
    bool HasRandomIdle = false;
    bool FollowMother = false;
    bool HasMotherTurtleStop = false;
    bool FirstTimeFound = false;
    bool IsPlayingSound = false;


    // On start of the game gets the referances for each variable and removes the UI from the screen.
    void Start () {
        UI = GameObject.FindObjectOfType<HUD>();
        turtleScript = GetComponent<Turtle>();
        motherShip = GameObject.FindGameObjectWithTag("MotherTurtle").GetComponentInParent<Mothership>();
        meshAgent = GetComponent<NavMeshAgent>();
        meshAgent.enabled = false;
        animator = GetComponent<Animator>();
        intract = GetComponentInChildren<Interact>();
    }



    void Update()
    {

        // Checks if the turtle has not been pickedup
        if (hasBeenPickup != true)
        {
            // Checks if the player inside the trigger. If inside then player can interact with turtle
            if (isInTrigger == true)
            {
                if (Input.GetButtonDown("Interact"))
                {
                    if (intract != null)
                    {
                        hasBeenPickup = true;
                        pHearts.Stop();
                        animator.SetBool("beenPickedUp", true);
                        playCollectParticle();
                        intract.DestroyInteract();
                        Invoke("FoundTurtle", 1.5f);
                        UI.showTurtleIcon = true;
                        UI.TurtleUICounter();
                        motherShip.foundTurtles.Add(gameObject);
                        motherShip.currentTurtles = motherShip.foundTurtles.Count;
                    }
                }
            }
        }
    }



    // Picked up the baby trutle will teleport the babytrutle to the mother and give the player some feedback that turtle just got pickup.
    // Also checking if this was the first turtle that was found or not and sets an index for the next turtle to use.
    void FoundTurtle()
    { 
        transform.position = new Vector3(motherShip.tempLocation.x, motherShip.tempLocation.y, motherShip.tempLocation.z);
        FirstTimeFound = true;
        animator.SetBool("beenFound", false);
        pCollect.Play();

        if (motherShip.foundTurtles.Count == 1)
        {
            FollowMother = true;
        } else {
            FollowID = motherShip.foundTurtles.Count - 2;
        }
        meshAgent.enabled = true;

    }


    //Checks if the player is close to the babytrutle and dippending if the turlte has been found or not will give diffrent reaction to the player.
    void OnTriggerEnter(Collider playerCheck)
    {

        if (playerCheck.gameObject.GetComponent<Player>() != null)
        {
            isInTrigger = true;
            pHearts.Play();
            if (FirstTimeFound)
            {
                 meshAgent.Stop();
                 animator.SetBool("beenFound", false);
                 animator.SetBool("Retracted", true);
            } else {
                animator.SetBool("beenFound", true);
            }
        }
    }


    // When the goes away from the babyturtle it then will resume to walk after the player or back to the mother if it has been found
    void OnTriggerExit(Collider playerCheck)
    {
        if (playerCheck.gameObject.GetComponent<Player>() != null)
        {
            isInTrigger = false;
            pHearts.Stop();
            if (motherShip.isMotherInShell == false)
                if (turtleScript.hasGoneOver == false)
                    if (FirstTimeFound)
                    {
                        meshAgent.Resume();
                        animator.SetBool("Retracted", false);
                    } else {
                        animator.SetBool("beenFound", false);
                    }
        }
    }

    // Plays a partical when the turtle has been colelcted
    void playCollectParticle()
    {
        if(!hasBeenPickup)
            if(!pCollect.isPlaying)
                pCollect.Play();
    }
}


If another baby turtle is picked up then that baby turtle will find the previous picked up turtle and start following that baby turtle.

Click Code to Expand

 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using UnityEngine;
using System.Collections;

public class BabyTurtle : MonoBehaviour {
    
    // Public

    [Header("Particles")]
    public ParticleSystem pCollect;

    // Hidden
    [HideInInspector]
    public NavMeshAgent meshAgent;

    // Private

    // References
    Mothership motherShip;
    Rigidbody rigd;
    Interact intract;
    Turtle turtleScript;
    Animator animator;

    // Variables
    int FollowID;
    bool FollowMother = false;
    bool FirstTimeFound = false;

    // On start of the game gets the referances for each variable and removes the UI from the screen.
    void Start () {
        turtleScript = GetComponent<Turtle>();
        motherShip = GameObject.FindGameObjectWithTag("MotherTurtle").GetComponentInParent<Mothership>();
        meshAgent = GetComponent<NavMeshAgent>();
        meshAgent.enabled = false;
        animator = GetComponent<Animator>();
        rigd = GetComponent<Rigidbody>();
        intract = GetComponentInChildren<Interact>();
    }


    void FoundTurtle()
    {
        transform.position = new Vector3(motherShip.tempLocation.x, motherShip.tempLocation.y, motherShip.tempLocation.z);
        FirstTimeFound = true;
        animator.SetBool("beenFound", false);
        pCollect.Play();

        if (motherShip.foundTurtles.Count == 1)
        {
            FollowMother = true;
        } else
        {
            FollowID = motherShip.foundTurtles.Count - 2;
        }
        meshAgent.enabled = true;

    }
}


If the mother turtle would go into a shell the then all the baby turtles that's been picked up will jump into their shells as well

Click Code to Expand

 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using UnityEngine;
using System.Collections;

public class BabyTurtle : MonoBehaviour {
    
    // Hidden
    [HideInInspector]
    public NavMeshAgent meshAgent;
    [HideInInspector]
    public bool hasBeenPickup = false;

    // Private

    // References
    Mothership motherShip;
    Transform Follow;
    Turtle turtleScript;
    Vector3 lastpos = Vector3.zero;
    Animator animator;

    // Variables
    int FollowID;
    bool isInTrigger = false;
    bool HasRandomIdle = false;
    bool FollowMother = false;


    // On start of the game gets the referances for each variable and removes the UI from the screen.
    void Start () {
        turtleScript = GetComponent<Turtle>();
        motherShip = GameObject.FindGameObjectWithTag("MotherTurtle").GetComponentInParent<Mothership>();
        meshAgent = GetComponent<NavMeshAgent>();
        meshAgent.enabled = false;
        animator = GetComponent<Animator>();
    }

	void Update () {

            // >Follow Types<(there is currently three follow types ( 1.Follow mother trutle, 2. follow the player, 3.Follow babytrutle infront of current ))
            //
            // Check if the current babyturtle should follow the mother or the baby turtle in front
            if (FollowMother == true)
            {
                // Checks if the babyturtle should follow the mother or the player(If the player is in the turtle area then babytrutles will start to follow the player)
                if(motherShip.AISphere.FollowPlayer == true)
                {
                    Follow = GameObject.FindGameObjectWithTag("Player").transform;
                } else {
                    Follow = motherShip.GetComponent<Transform>();
                }
            // checks for the babytrutle that was pickedup befor the current one and follows that one(makes the turtles walk in a snake/line form after the mother)
            } else {
                Follow = motherShip.foundTurtles[FollowID].GetComponent<Transform>();
            }


            // makes the movement from the previous set follow type.
            if (meshAgent.enabled == true)
            {
                meshAgent.SetDestination(Follow.position);
            }

            // Makes a velocity to later check if the turtle has a movement
            float velocity = Vector3.Distance(lastpos, transform.position) / Time.deltaTime;
            lastpos = transform.position;
            
            // checks if the mothertrutle is in shell then all small turtles will go into shell aswell 
            if(hasBeenPickup == true && motherShip.isMotherInShell == true) 
            {
                animator.SetBool("Retracted", true);
                meshAgent.Stop();
            }

            // This make the baby turtle go out from its shell and make it walk or idle again
            if (hasBeenPickup == true && isInTrigger == false && turtleScript.hasGoneOver == false && motherShip.isMotherInShell == false)
                if (velocity >= 0.09f)
                {
                    animator.SetBool("Retracted", false);
                    animator.SetFloat("Speed", velocity);
                    meshAgent.Resume();
                    HasRandomIdle = false;
                }
        }
}