This project serves as a reconstuction of the first level (Emerald Coast) of the original ‘Sonic Adventure’ for the Sega Dreamcast. This project is made by five people using the Unity Engine and the language ‘C#’. The development team contains two programmers and three game artists.
A ‘Vertical Slice’ refers to a piece of gameplay, lasting approximately 10 seconds. A piece from the first level is usually picked to make it easier to compare gameplay between the original game and the Vertical Slice. With this project, Wayne was able to prove himself capable of implementing gameplay features that are shown in the first level of the actual game.
The player (Sonic) drops rings in a circle pattern when he gets hit by hazardous objects, like the spikes shown below. The pattern at which the player drops rings is determined by the amount of rings Sonic possesses. The angle at which the rings drop is then determined by dividing the circle by that amount.

The original game contains automatic camera movement that follows the player (Sonic) based on his progress in the level. The ‘AutoCamera’-class is implemented to fill in that role, while also maintaining a fixed view of the player while he/she runs on the loop. The camera then switches back to the original position at which it can follow the player.
private int ShootRings(int maxAmount)
{
BoxCollider[] thisRingCollider = new BoxCollider[maxAmount];
StartCoroutine(“Damage”);
AudioManager.instance.Play(“LosingRings”);
float[] shootingAngle = new float[3];
shootingAngle[0] = 0; //Angle in radians
shootingAngle[1] = 1; //X-value based on angle
shootingAngle[2] = 0; //Z-value based on angle
for (int i = 0; i < maxAmount; i++)
{
shootingAngle[1] = Mathf.Cos(shootingAngle[0]);
shootingAngle[2] = -Mathf.Sin(shootingAngle[0]);
GameObject thisRing;
thisRing = Instantiate(ring, transform.position, transform.rotation);
thisRing.transform.parent = itemlist;
thisRing.GetComponent<RingBehaviour>().droppedItem = true;
Rigidbody ringBehaviour = thisRing.GetComponent<Rigidbody>();
ringBehaviour.AddForce((itemlist.transform.up * 2 +
new Vector3(shootingAngle[1], 0.0f, shootingAngle[2])) *
SHOOTING_RADIUS);
Destroy(thisRing, Constants.Value.ringSeconds);
shootingAngle[0] += ((2 * Mathf.PI) / maxAmount);
}
ringColliders = thisRingCollider;
ringAmount[1] = maxAmount;
return 0;
}
private void SetOffset(bool trigger, Collider collision)
{
switch(collision.name)
{
case Constants.Trigger.name_0:
if (_player.CurrentVel.z >= 0.0f) {
//Slightly tilted camera angle when Sonic goes out of the cave
_offset = Vector3.MoveTowards(_offset, _offsetList[1], 40.0f *
Time.deltaTime);
}
else {
//Camera angle goes back to normal
_offset = Vector3.MoveTowards(_offset, _offsetList[0], 40.0f *
Time.deltaTime);
}
break;
case Constants.Trigger.name_1:
if (_player.CurrentVel.z > 0.0f) {
//Camera turns towards loop direction
_offset = Vector3.MoveTowards(_offset, _offsetList[2], 16.5f *
(playerMovement.Speed / playerMovement.MaxSpeed) * Time.deltaTime);
}
else if (_player.CurrentVel.x < 0.0f) {
//Camera angle goes back to before
_offset = Vector3.MoveTowards(_offset, _offsetList[1], 16.5f *
(playerMovement.Speed / playerMovement.MaxSpeed) * Time.deltaTime);
}
break;
case Constants.Trigger.name_2:
//Camera is located outside the loop
_offset = _offsetList[3];
transform.position = _offsetList[3];
break;
case Constants.Trigger.name_3:
//Camera changes back to face bridge direction
_offset = Vector3.MoveTowards(_offset, _offsetList[2], 60.0f *
Time.deltaTime);
break;
default:
//Regular camera offset
_offset = _offsetList[0];
break;
}
}