The Ecology

The ecology project involves every assignment we have done in the course so far, as well as story telling aspects.

story board : Sand Dooms

The story:

A hidden island exists in unexplored waters which human society has never reached because of its mysterious, powerful barrier. The landscape appears typical at first but the island shows signs of being alive through its sand dunes which take the form of spikes dunes, and deserted valleys. The sand exists with consciousness because it continuously transforms itself into different landforms which include cliffs and slopes and mountain peaks that reach high altitudes. The entire island maintains a state of constant motion.


The story starts when the Cylinder, where main camera would be placed, emerges from the shore after a shipwreck that occurred under unknown circumstances. She starts to explore the strange environment while being alone because she has no sense of direction and she uses the camera to see from her own point of view. But the island is not empty. The sand dunes produce MShape, which takes the shape of a threatening skull-like being. MShape was once in the same situation as Cylinder, before his remains were consumed by the ever-mighty sand. The island consumed him to create a protective guardian who now serves as a sand-driven guard.


The sand develops an intense desire to dominate every new spirit which enters the world. MShape notices the Cylinder’s presence which causes the sand to bring back his body shape so he can start his pursuit to capture her form. His radiant eyes together with his transforming body shape indicate that the island environment is hostile to him. The landscape follows his movements because hills emerge from the ground while paths change direction and dunes transform into ramps which enable him to pursue her at increased speed.
The island maintains a hidden sanctuary which exists within its mountainous heights. The area stands as the single spot which the sand grains fail to access. The altitude weakens its influence until it reaches a small area where its power disappears.

The Cylinder needs to reach sufficient height, at the top of the boarding dunes, to break free from MShape’s hold while she survives until she discovers the island’s hidden secrets.
She navigates through unstable terrain which features sand that breaks down unpredictably to create new barriers and reshape the environment. The mountains display a living quality because MShape moves through them like an endless bone and dust avalanche. She must respond instantly to each situation by using her jumping skills and her ability to run while she navigates through the environment.
The story develops into a speed competition between MShape and its predators while the survivor fights for survival.


The Cylinder will it succeed in reaching the protected area which lies at the summit of the peaks or will the sand bury her as it did to the previous victim?

Process

Codes

For clarity purposes, none of these codes were developed by me personally, I simply gave prompts to ChatGPT and asked for the codes in #C. all codes listed below are AI generated.

CharacterMovement.cs

using UnityEngine;

public class CharacterMovement : MonoBehaviour
{
public float moveSpeed = 5f;
public float jumpForce = 5f;
public float gravity = -9.81f;

private CharacterController controller;
private Vector3 velocity;

void Start()
{
    controller = GetComponent<CharacterController>();
}

void Update()
{
    // Basic movement (WASD)
    float x = Input.GetAxis("Horizontal");
    float z = Input.GetAxis("Vertical");

    Vector3 move = transform.right * x + transform.forward * z;
    controller.Move(move * moveSpeed * Time.deltaTime);

    // Jump
    if (controller.isGrounded && velocity.y < 0)
        velocity.y = -2f;

    if (Input.GetButtonDown("Jump") && controller.isGrounded)
        velocity.y = jumpForce;

    // Gravity
    velocity.y += gravity * Time.deltaTime;
    controller.Move(velocity * Time.deltaTime);
}

}

CharacterCamera.cs

using UnityEngine;

public class CharacterCamera : MonoBehaviour
{
public float mouseSensitivity = 150f;
public Transform playerBody;

float xRotation = 0f;

void Start()
{
    Cursor.lockState = CursorLockMode.Locked;
}

void Update()
{
    float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
    float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

    // Up-down rotation (Camera only)
    xRotation -= mouseY;
    xRotation = Mathf.Clamp(xRotation, -70f, 70f);

    transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);

    // Left-right rotation rotates the whole player (so movement aligns)
    playerBody.Rotate(Vector3.up * mouseX);
}

}

MShapeChase.cs

using UnityEngine;
using UnityEngine.SceneManagement;

public class MShapeChase : MonoBehaviour
{
public Transform player;
public float chaseSpeed = 5f;
public float slowSpeed = 2f;
public float detectionRange = 50f;

private float currentSpeed;
private CharacterController controller;

void Start()
{
    controller = GetComponent<CharacterController>();
    currentSpeed = chaseSpeed;
}

void Update()
{
    if (player == null) return;

    float distance = Vector3.Distance(transform.position, player.position);
    if (distance > detectionRange) return;

    Vector3 direction = (player.position - transform.position).normalized;
    Vector3 movement = direction * currentSpeed * Time.deltaTime;

    movement.y += -10f * Time.deltaTime;   // gravity so he doesn't float

    controller.Move(movement);

    transform.LookAt(player);
}

// Called from the player's script whenever they jump
public void SlowDownOnPlayerJump()
{
    currentSpeed = slowSpeed;
    CancelInvoke(nameof(ResetSpeed));
    Invoke(nameof(ResetSpeed), 1.5f); // slow down for 1.5 sec
}

private void ResetSpeed()
{
    currentSpeed = chaseSpeed;
}

private void OnControllerColliderHit(ControllerColliderHit hit)
{
    if (hit.gameObject.CompareTag("Player"))
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }
}

Payer jump script

using UnityEngine;

public class CharacterMovement : MonoBehaviour
{
public float moveSpeed = 5f;
public float jumpForce = 5f;
public float gravity = -9.81f;

private CharacterController controller;
private Vector3 velocity;

private MShapeChase mshape; 

void Start()
{
    controller = GetComponent<CharacterController>();
    mshape = FindObjectOfType<MShapeChase>(); // finds the chaser
}

void Update()
{
    float x = Input.GetAxis("Horizontal");
    float z = Input.GetAxis("Vertical");

    Vector3 move = transform.right * x + transform.forward * z;
    controller.Move(move * moveSpeed * Time.deltaTime);

    if (controller.isGrounded && velocity.y < 0)
        velocity.y = -2f;

    if (Input.GetButtonDown("Jump") && controller.isGrounded)
    {
        velocity.y = jumpForce;

        if (mshape != null)
            mshape.SlowDownOnPlayerJump();
    }

    velocity.y += gravity * Time.deltaTime;
    controller.Move(velocity * Time.deltaTime);
}

}

I was excited when I began developing my game for Ecology of Forms because the narrative and gameplay design seemed completely original to me. I started by bringing my terrain into Unity before using different sculpting brushes to build the sandy mountain environment which followed my storyboard design. I dedicated a lot of time to create the peaks while I worked on making the valleys smooth and I aimed to achieve a shifting-sand effect for the entire island. I imported my MShape 3D scan STL file and applied materials to create an antagonist design which matched my desired eerie appearance.
I introduced the Cylinder as my player character, and tested different ways of scaling MShape and its transformations to its X, Y and Z dimensions. I used the shape again to create environmental elements which included clouds through different stretching techniques that maintained the overall unity of the space. The environment matched my storyboard drawing so I was satisfied with how everything turned out.


My issue began when I started implementing the scripts.
Unity displayed an error message which indicated that a script was missing but I was unable to locate its attachment point. I entered “T Missing” into the hierarchy search bar following all online tutorial instructions but the search results remained empty. The system contains no hidden objects and all scripts have proper tags. I reviewed my code multiple times but failed to discover which script was missing its reference. I removed all objects from the hierarchy except the terrain but the error persisted.
I spent the entire night from 6–7 a.m. speaking with ChatGPT while I attempted all available solutions and troubleshooting steps and system repair techniques, I ended up with 173 warnings on the bottom of the screen, as shown in the screenshot. The hierarchy and inspector and assets and console and script reimports did not resolve the issue. I experienced complete exhaustion and anger because I had spent time developing the game concept and environment and characters and the game was almost ready for play.
The professor advised me to remove Unity from my system and perform a fresh installation but the submission deadline had already arrived at that point. The professor advised me to uninstall Unity but I did not have enough time to rebuild the terrain and re-import assets and recreate all details because the submission deadline had already passed. The experience brought me deep disappointment because I had developed strong affection for my story concept which included a mysterious island and a sand creature and their desperate race to reach the protected mountain summit.


The project taught me valuable lessons about game development although I failed to complete it. The production can have all its elements in place including strong concepts and scenic locations and prepared performers yet software problems will bring everything to a standstill. I believe switching to a different engine or beginning my work at an earlier stage with additional backup systems would enable me to create this world according to my first vision.