Sie sind auf Seite 1von 38

ABSTRACT

This report describes the design and implementation of a 3D game called Maze
Runner. The game is created using Unity-3D where the player works his/her way
through a maze consisting eight rooms. Each room introduces certain tasks the
player must perform in order to progress through the game. The objective of the
game is to navigate through the maze and perform the tasks required to reach
the final room and win the game.

Table of Content
ABSTRACT .....................................................................................................................
Table of Content ..............................................................................................................
List of Figures ..................................................................................................................
1.0 INTRODUCTION ......................................................................................................
2.0 GAME OVERVIEW ..................................................................................................
2.1 Game Concept and Goals .......................................................................................
2.2 User Controls ..........................................................................................................
2.3 Scene layout ............................................................................................................
3.0 SOFTWARE ARCHITECTURE ...............................................................................
4.0 MAIN FEATURES ....................................................................................................
4.1 Basic Features .........................................................................................................
4.2 Advanced Features ...............................................................................................
5.0 GAME DESCRIPTION ...........................................................................................
5.1 3D Maze ............................................................................................................
5.2 Rooms ................................................................................................................
6.0 DIFFICULTIES FACED ..........................................................................................
7.0 FUTURE IMPROVEMENTS ..................................................................................
8.0 CONCLUSION .......................................................................................................

Reference.....................................................................................................

List of Figures

Figure 2.3.1 - World Plane Layout


Figure 2.3.2 - World Plane Coordinates
Figure 3.0.1 - Architecture Block Diagram...
Figure 4.1.1 - Free Camera View
Figure 4.1.2 - First Person View..
** Figure 4.1.3 - Second Person View.
Figure 4.1.7- Coins Screenshot..
Figure 4.1.11 - Walls.
Figure 4.1.12 - Grass..
Figure 4.1.13 - wood.
Figure 4.1.14 - Rocks..
**Figure 4.2.1 - Snow..
Figure 4.2.2 - Trees ...
Figure 4.2.3 - Rooms ...
Figure 4.2.4 - ...
Figure 4.2.5 - Sound Effect
Figure 5.1.1 3 - D Maze Overview..
Figure 5.2.1 - Room 1..
Figure 5.2.2 - Room 2..
Figure 5.2.3 - Room 3..
Figure 5.2.4 - Room 4..
Figure 5.2.5 - Room 5..
Figure 5.2.6 - Room 6..
Figure 5.2.7 - Room 7..
Figure 5.2.8 - Room 8..

1.0

INTRODUCTION
Creating a 3D game in Unity-3D is both challenging and rewarding. There
are many resources and libraries available to create a very realistic and
high-end video game. We were able to make use of these resources to
create a 3D maze game called the Maze Runner. This game requires
navigating through a 3D maze as well as solving riddles and puzzles to
finish the game. By implementing advanced features, the overall game
play quality went up as well as the look and feel of the game. We learned
all the basics to designing and implementing a 3D game in Unity-3D as
well as some of the more advanced techniques used when creating such a
game. Much of our time was spent on adding features to the game as well
as improving the storyline of the game. We were able to create an
interesting game that was a mix of 3D maze game and other role playing
games.

2.0

GAME OVERVIEW

The game idea chosen for our project is a 3D maze. The first reason behind this
decision is that in a 3d maze we can explore any area we would like to develop
models for. We can construct furniture, animals, space objects, wizards, different
themes in different rooms. The idea seemed very practical for this project, and
left a large room for creativity. The second reason we all unanimously accepted
this idea is that we were all apparently affected by games of this style such as
Final Fantasy, Resident Evil etc... The idea behind the game is to make the maze
full of puzzles and mysterious themes.

Game Concept and Goals:


The main objective of the game is to collect all coins by performing the steps
and hints given in each room. The player may have to visit a room more than
once as the steps must be performed in sequence for the player to obtain the
coins. There are a total of eight rooms where each room represents a new
challenge for the player. Each room has its own theme to match the action to be
performed. Hints are provided by writings on walls as well as player interaction
with the models in the game.

2.2 User Controls :


Game is very hard to play if it is difficult to control the player; we implemented
easy and intuitive user controls to help ease the learning curve of the game so
that anyone can pickup on the game quickly. By using the mouse to look as well
as point toward the direction the player will move toward, it makes it very easy
for the user the control their player. On top of the basic movement controls, the
player is capable of performing several tasks throughout the game. The actions
that can be performed include; pickup, open and use. Following is the summary
of actions allowed in the game:
Shift - Move Fast
Space - Jump
Arrow Key Up Move forward
Arrow Key Down Move backward
Arrow Key Left Move left
Arrow Key Right Move right

2.3 Scene layout


The first thing we did is that we tried to draw up a scene plan. This took much
iteration before we reached the one we have now. However, it was important to
have such blueprints of the maze, because it made it easier in communication
between groups.
When it came to the translation of objects, and the development of the
restrictions this plan proved very useful. The diagram below shows the layout.
The color codes represent different aspects of the code. The side axes represent
the x-axis and the z-axis in the game.
The color coding can be described as follows:
Grey: Restricted area
Yellow: The rooms
Purple: Horizontal corridors
Sky blue: Vertical corridors

8.0

CONCLUSION

It was a challenge to create a fun, working and visually interesting 3D


game in the timeframe given to us. We were able to create a 3D maze
game that also required thinking and problem solving. Our game required
the use of several external resources and libraries as well as our own way
of implementing basic and advanced features to the game. Some of the
key advanced features implemented were transparency, collision,
detection and sound effects. Adding such features improved the game
play and showed what Unity-3D was capable of doing when creating a 3D
game. Our group learned many interesting techniques involved in creating
a 3D game and this project gave us an insight to what game creation
process was like. Overall, our Maze Runner game was a success that has
functions and advanced features as well.

6.0 DIFFICULTIES FACED


In the camera part, looking at different directions is achieved by rotating
the world around the camera. This achieved the objective, but made it
difficult to implement features that are related to the camera.
First, when we wanted to do the second person view, we faced some
difficulty when placing the camera behind the main character since the
character will rotate with the world when the player looks into different
directions. Therefore, we had to draw the main character before doing the
rotations for the whole world one time for the second person view, and
drawing the main character again after the rotations for the free
moving camera and first person view. This difference in the location of the
draw function for the main character is controlled by a Boolean. If the
camera was rotated to achieve the view rotations, we would not have
needed to do that.
Second, when we have placed one light to imitate the sun effect, the
position of the light looked like it was changing when we rotate the world.
In fact, the light is fixed, but because the world rotates and the camera
does not rotate with the world, the light looked like it was changing
direction with respect to the world. To overcome this difficulty, we
had to change the position of the light source according to how much the
world has been rotated, so we have a moving light with the world now.
However, moving the light to the right position every time the world is
rotated has created the effect of a fixed light in one direction that we
originally wanted.
When it came to designing the floor and the walls, we needed a quick way
to generate them, with a code template. So the difficulty was in actually
creating the loops and the draw functions that will suite our need.
Also for the restrictions and the collision detection, it was not easy to
immediately think of a way to implement them. We had to brainstorm
more than once to make sure that this will apply to all our cases. Not only
that but how we are going to manage the functions.
This leads us to another difficulty we faced, which was actually how each
part was going to interact with one another. We needed to make it
modular, which was not very clear how that was going to happen at first
glance. It required us to sit down see each group members strengths so
that we could assign tasks and modules accordingly. We then developed a
way of communication that was efficient.
As with any software development, difficulties will arise and its our job as
software engineers to overcome these obstacles by doing researching and
collaborating. Our group did a great job communicating with each other
when we ran into problems and made sure that we were on track to finish
the project.

Player Control Module:


using UnityEngine;
using System.Collections;
public class player_controller : MonoBehaviour {
private Rigidbody rb;
public float speed;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rb.AddForce (movement*speed);
}

Time Module:
using UnityEngine;
using System.Collections;
public class timer : MonoBehaviour {
float timeRemaining=30;
void Start () {
}
void Update () {
timeRemaining -= Time.deltaTime;
}
void OnGUI(){
if (timeRemaining>0){
GUI.Label (new Rect (100, 100, 200,100),"TimeRemaining = "+
(int)timeRemaining);
}
else{
GUI.Label (new Rect (100, 100, 100, 100), " Game Over ");
}
}
}

Camera control:
using UnityEngine;
using System.Collections;
public class cameracontroller : MonoBehaviour {
public GameObject player;
private Vector3 offset;
void Start () {
}

offset = transform.position - player.transform.position;

void LateUpdate () {
}

transform.position = player.transform.position + offset;

Door Module:
using UnityEngine;
using System.Collections;
using System;
public class doors : MonoBehaviour {
Animator animator;
bool DoorOpen;
void Start(){
DoorOpen = false;
animator = GetComponent<Animator> ();
}
void OnTriggerEnter(Collider other){
if (other.gameObject.tag == "Player") {
DoorOpen = true;
door ("Open");
}
}
void OnTriggerExit(Collider other)
{
if (DoorOpen) {
DoorOpen = false;
door ("Close");
}
}
void door(String direction)
{
animator.SetTrigger(direction);
}
}

Pickup Module:
using UnityEngine;
using System.Collections;
public class PickUp : MonoBehaviour {

void Update () {
transform.Rotate (new Vector3 (0, 180,0 )*Time.deltaTime);
}
}

Drag Rigid Body:

using System;
using System.Collections;
using UnityEngine;
namespace UnityStandardAssets.Utility
{
public class DragRigidbody : MonoBehaviour
{
const float k_Spring = 50.0f;
const float k_Damper = 5.0f;
const float k_Drag = 10.0f;
const float k_AngularDrag = 5.0f;
const float k_Distance = 0.2f;
const bool k_AttachToCenterOfMass = false;
private SpringJoint m_SpringJoint;
private void Update()
{
// Make sure the user pressed the mouse down
if (!Input.GetMouseButtonDown(0))
{
return;
}

var mainCamera = FindCamera();


// We need to actually hit an object
RaycastHit hit = new RaycastHit();
if (
!
Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition).origi
n,
mainCamera.ScreenPointToRay(Input.mousePosition).
direction, out hit, 100,
Physics.DefaultRaycastLayers))
{
return;
}
// We need to hit a rigidbody that is not kinematic
if (!hit.rigidbody || hit.rigidbody.isKinematic)
{
return;
}
if (!m_SpringJoint)
{
var go = new GameObject("Rigidbody dragger");
Rigidbody body = go.AddComponent<Rigidbody>();
m_SpringJoint = go.AddComponent<SpringJoint>();
body.isKinematic = true;
}
m_SpringJoint.transform.position = hit.point;
m_SpringJoint.anchor = Vector3.zero;
m_SpringJoint.spring = k_Spring;
m_SpringJoint.damper = k_Damper;
m_SpringJoint.maxDistance = k_Distance;
m_SpringJoint.connectedBody = hit.rigidbody;
StartCoroutine("DragObject", hit.distance);
}
private IEnumerator DragObject(float distance)
{
var oldDrag = m_SpringJoint.connectedBody.drag;
var oldAngularDrag = m_SpringJoint.connectedBody.angularDrag;
m_SpringJoint.connectedBody.drag = k_Drag;
m_SpringJoint.connectedBody.angularDrag = k_AngularDrag;
var mainCamera = FindCamera();
while (Input.GetMouseButton(0))
{

var ray = mainCamera.ScreenPointToRay(Input.mousePosition);


m_SpringJoint.transform.position = ray.GetPoint(distance);
yield return null;
}
if (m_SpringJoint.connectedBody)
{
m_SpringJoint.connectedBody.drag = oldDrag;
m_SpringJoint.connectedBody.angularDrag = oldAngularDrag;
m_SpringJoint.connectedBody = null;
}
}
private Camera FindCamera()
{
if (GetComponent<Camera>())
{
return GetComponent<Camera>();
}
return Camera.main;
}
}
}

Camera Refocus:
using System;
using UnityEngine;
namespace UnityStandardAssets.Utility
{
public class CameraRefocus
{
public Camera Camera;
public Vector3 Lookatpoint;
public Transform Parent;
private Vector3 m_OrigCameraPos;
private bool m_Refocus;
public CameraRefocus(Camera camera, Transform parent, Vector3 ori
gCameraPos)
{
m_OrigCameraPos = origCameraPos;

Camera = camera;
Parent = parent;
}
public void ChangeCamera(Camera camera)
{
Camera = camera;
}
public void ChangeParent(Transform parent)
{
Parent = parent;
}
public void GetFocusPoint()
{
RaycastHit hitInfo;
if (Physics.Raycast(Parent.transform.position + m_OrigCameraPos,
Parent.transform.forward, out hitInfo,
100f))
{
Lookatpoint = hitInfo.point;
m_Refocus = true;
return;
}
m_Refocus = false;
}
public void SetFocusPoint()
{
if (m_Refocus)
{
Camera.transform.LookAt(Lookatpoint);
}
}
}
}

Mouse Look:
using System;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;

namespace UnityStandardAssets.Characters.FirstPerson
{
[Serializable]
public class MouseLook
{
public float XSensitivity = 2f;
public float YSensitivity = 2f;
public bool clampVerticalRotation = true;
public float MinimumX = -90F;
public float MaximumX = 90F;
public bool smooth;
public float smoothTime = 5f;
public bool lockCursor = true;
private Quaternion m_CharacterTargetRot;
private Quaternion m_CameraTargetRot;
private bool m_cursorIsLocked = true;
public void Init(Transform character, Transform camera)
{
m_CharacterTargetRot = character.localRotation;
m_CameraTargetRot = camera.localRotation;
}
public void LookRotation(Transform character, Transform camera)
{
float yRot = CrossPlatformInputManager.GetAxis("Mouse X") * XSe
nsitivity;
float xRot = CrossPlatformInputManager.GetAxis("Mouse Y") * YSe
nsitivity;
m_CharacterTargetRot *= Quaternion.Euler (0f, yRot, 0f);
m_CameraTargetRot *= Quaternion.Euler (-xRot, 0f, 0f);
if(clampVerticalRotation)
m_CameraTargetRot = ClampRotationAroundXAxis (m_CameraTa
rgetRot);
if(smooth)
{
character.localRotation = Quaternion.Slerp (character.localRotati
on, m_CharacterTargetRot,
smoothTime * Time.deltaTime);
camera.localRotation = Quaternion.Slerp (camera.localRotation,
m_CameraTargetRot,
smoothTime * Time.deltaTime);

}
else
{
character.localRotation = m_CharacterTargetRot;
camera.localRotation = m_CameraTargetRot;
}
UpdateCursorLock();
}
public void SetCursorLock(bool value)
{
lockCursor = value;
if(!lockCursor)
{//we force unlock the cursor if the user disable the cursor locking
helper
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
}
public void UpdateCursorLock()
{
//if the user set "lockCursor" we check & properly lock the cursos
if (lockCursor)
InternalLockUpdate();
}
private void InternalLockUpdate()
{
if(Input.GetKeyUp(KeyCode.Escape))
{
m_cursorIsLocked = false;
}
else if(Input.GetMouseButtonUp(0))
{
m_cursorIsLocked = true;
}
if (m_cursorIsLocked)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
else if (!m_cursorIsLocked)
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}

}
Quaternion ClampRotationAroundXAxis(Quaternion q)
{
q.x /= q.w;
q.y /= q.w;
q.z /= q.w;
q.w = 1.0f;
float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);
angleX = Mathf.Clamp (angleX, MinimumX, MaximumX);
q.x = Mathf.Tan (0.5f * Mathf.Deg2Rad * angleX);
return q;
}
}
}

Third Person User Control:


using System;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
namespace UnityStandardAssets.Characters.ThirdPerson
{
[RequireComponent(typeof (ThirdPersonCharacter))]
public class ThirdPersonUserControl : MonoBehaviour
{
private ThirdPersonCharacter m_Character; // A reference to the Thir
dPersonCharacter on the object
private Transform m_Cam;
// A reference to the main came
ra in the scenes transform
private Vector3 m_CamForward;
// The current forward directi
on of the camera
private Vector3 m_Move;
private bool m_Jump;
// the world-relative desired move
direction, calculated from the camForward and user input.
private void Start()
{

// get the transform of the main camera


if (Camera.main != null)
{
m_Cam = Camera.main.transform;
}
else
{
Debug.LogWarning(
"Warning: no main camera found. Third person character nee
ds a Camera tagged \"MainCamera\", for camera-relative controls.");
// we use self-relative controls in this case, which probably isn't
what the user wants, but hey, we warned them!
}
// get the third person character ( this should never be null due to
require component )
m_Character = GetComponent<ThirdPersonCharacter>();
}
private void Update()
{
if (!m_Jump)
{
m_Jump = CrossPlatformInputManager.GetButtonDown("Jump");
}
}
// Fixed update is called in sync with physics
private void FixedUpdate()
{
// read inputs
float h = CrossPlatformInputManager.GetAxis("Horizontal");
float v = CrossPlatformInputManager.GetAxis("Vertical");
bool crouch = Input.GetKey(KeyCode.C);
// calculate move direction to pass to character
if (m_Cam != null)
{
// calculate camera relative direction to move:
m_CamForward = Vector3.Scale(m_Cam.forward, new Vector3(1
, 0, 1)).normalized;
m_Move = v*m_CamForward + h*m_Cam.right;
}
else
{
// we use world-relative directions in the case of no main camer
a

m_Move = v*Vector3.forward + h*Vector3.right;


}
#if !MOBILE_INPUT
// walk speed multiplier
if (Input.GetKey(KeyCode.LeftShift)) m_Move *= 0.5f;
#endif
// pass all parameters to the character control script
m_Character.Move(m_Move, crouch, m_Jump);
m_Jump = false;
}
}
}

Third person Character :


using UnityEngine;
namespace UnityStandardAssets.Characters.ThirdPerson
{
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]
[RequireComponent(typeof(Animator))]
public class ThirdPersonCharacter : MonoBehaviour
{
[SerializeField] float m_MovingTurnSpeed = 360;
[SerializeField] float m_StationaryTurnSpeed = 180;
[SerializeField] float m_JumpPower = 12f;
[Range(1f, 4f)][SerializeField] float m_GravityMultiplier = 2f;
[SerializeField] float m_RunCycleLegOffset = 0.2f; //specific to the ch
aracter in sample assets, will need to be modified to work with others
[SerializeField] float m_MoveSpeedMultiplier = 1f;
[SerializeField] float m_AnimSpeedMultiplier = 1f;
[SerializeField] float m_GroundCheckDistance = 0.1f;
Rigidbody m_Rigidbody;
Animator m_Animator;
bool m_IsGrounded;
float m_OrigGroundCheckDistance;
const float k_Half = 0.5f;
float m_TurnAmount;
float m_ForwardAmount;
Vector3 m_GroundNormal;
float m_CapsuleHeight;
Vector3 m_CapsuleCenter;
CapsuleCollider m_Capsule;
bool m_Crouching;

void Start()
{
m_Animator = GetComponent<Animator>();
m_Rigidbody = GetComponent<Rigidbody>();
m_Capsule = GetComponent<CapsuleCollider>();
m_CapsuleHeight = m_Capsule.height;
m_CapsuleCenter = m_Capsule.center;
m_Rigidbody.constraints = RigidbodyConstraints.FreezeRotationX |
RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotati
onZ;
m_OrigGroundCheckDistance = m_GroundCheckDistance;
}
public void Move(Vector3 move, bool crouch, bool jump)
{
// convert the world relative moveInput vector into a local-relative
// turn amount and forward amount required to head in the desired
// direction.
if (move.magnitude > 1f) move.Normalize();
move = transform.InverseTransformDirection(move);
CheckGroundStatus();
move = Vector3.ProjectOnPlane(move, m_GroundNormal);
m_TurnAmount = Mathf.Atan2(move.x, move.z);
m_ForwardAmount = move.z;
ApplyExtraTurnRotation();
// control and velocity handling is different when grounded and air
borne:
if (m_IsGrounded)
{
HandleGroundedMovement(crouch, jump);
}
else
{
HandleAirborneMovement();
}
ScaleCapsuleForCrouching(crouch);
PreventStandingInLowHeadroom();
// send input and other state parameters to the animator
UpdateAnimator(move);
}

void ScaleCapsuleForCrouching(bool crouch)


{
if (m_IsGrounded && crouch)
{
if (m_Crouching) return;
m_Capsule.height = m_Capsule.height / 2f;
m_Capsule.center = m_Capsule.center / 2f;
m_Crouching = true;
}
else
{
Ray crouchRay = new Ray(m_Rigidbody.position + Vector3.up *
m_Capsule.radius * k_Half, Vector3.up);
float crouchRayLength = m_CapsuleHeight - m_Capsule.radius *
k_Half;
if (Physics.SphereCast(crouchRay, m_Capsule.radius * k_Half, cr
ouchRayLength, ~0, QueryTriggerInteraction.Ignore))
{
m_Crouching = true;
return;
}
m_Capsule.height = m_CapsuleHeight;
m_Capsule.center = m_CapsuleCenter;
m_Crouching = false;
}
}
void PreventStandingInLowHeadroom()
{
// prevent standing up in crouch-only zones
if (!m_Crouching)
{
Ray crouchRay = new Ray(m_Rigidbody.position + Vector3.up *
m_Capsule.radius * k_Half, Vector3.up);
float crouchRayLength = m_CapsuleHeight - m_Capsule.radius *
k_Half;
if (Physics.SphereCast(crouchRay, m_Capsule.radius * k_Half, cr
ouchRayLength, ~0, QueryTriggerInteraction.Ignore))
{
m_Crouching = true;
}
}
}
void UpdateAnimator(Vector3 move)
{

// update the animator parameters


m_Animator.SetFloat("Forward", m_ForwardAmount, 0.1f, Time.delt
aTime);
m_Animator.SetFloat("Turn", m_TurnAmount, 0.1f, Time.deltaTime);
m_Animator.SetBool("Crouch", m_Crouching);
m_Animator.SetBool("OnGround", m_IsGrounded);
if (!m_IsGrounded)
{
m_Animator.SetFloat("Jump", m_Rigidbody.velocity.y);
}
// calculate which leg is behind, so as to leave that leg trailing in th
e jump animation
// (This code is reliant on the specific run cycle offset in our animat
ions,
// and assumes one leg passes the other at the normalized clip tim
es of 0.0 and 0.5)
float runCycle =
Mathf.Repeat(
m_Animator.GetCurrentAnimatorStateInfo(0).normalizedTime
+ m_RunCycleLegOffset, 1);
float jumpLeg = (runCycle < k_Half ? 1 : -1) * m_ForwardAmount;
if (m_IsGrounded)
{
m_Animator.SetFloat("JumpLeg", jumpLeg);
}
// the anim speed multiplier allows the overall speed of walking/ru
nning to be tweaked in the inspector,
// which affects the movement speed because of the root motion.
if (m_IsGrounded && move.magnitude > 0)
{
m_Animator.speed = m_AnimSpeedMultiplier;
}
else
{
// don't use that while airborne
m_Animator.speed = 1;
}
}
void HandleAirborneMovement()
{
// apply extra gravity from multiplier:
Vector3 extraGravityForce = (Physics.gravity * m_GravityMultiplier)
- Physics.gravity;
m_Rigidbody.AddForce(extraGravityForce);

m_GroundCheckDistance = m_Rigidbody.velocity.y < 0 ? m_OrigGr


oundCheckDistance : 0.01f;
}
void HandleGroundedMovement(bool crouch, bool jump)
{
// check whether conditions are right to allow a jump:
if (jump && !crouch && m_Animator.GetCurrentAnimatorStateInfo
(0).IsName("Grounded"))
{
// jump!
m_Rigidbody.velocity = new Vector3(m_Rigidbody.velocity.x, m_J
umpPower, m_Rigidbody.velocity.z);
m_IsGrounded = false;
m_Animator.applyRootMotion = false;
m_GroundCheckDistance = 0.1f;
}
}
void ApplyExtraTurnRotation()
{
// help the character turn faster (this is in addition to root rotation i
n the animation)
float turnSpeed = Mathf.Lerp(m_StationaryTurnSpeed, m_MovingTu
rnSpeed, m_ForwardAmount);
transform.Rotate(0, m_TurnAmount * turnSpeed * Time.deltaTime,
0);
}
public void OnAnimatorMove()
{
// we implement this function to override the default root motion.
// this allows us to modify the positional speed before it's applied.
if (m_IsGrounded && Time.deltaTime > 0)
{
Vector3 v = (m_Animator.deltaPosition * m_MoveSpeedMultiplier
) / Time.deltaTime;
// we preserve the existing y part of the current velocity.
v.y = m_Rigidbody.velocity.y;
m_Rigidbody.velocity = v;
}
}
void CheckGroundStatus()
{

RaycastHit hitInfo;
#if UNITY_EDITOR
// helper to visualise the ground check ray in the scene view
Debug.DrawLine(transform.position + (Vector3.up * 0.1f), transfor
m.position + (Vector3.up * 0.1f) + (Vector3.down * m_GroundCheckDistan
ce));
#endif
// 0.1f is a small offset to start the ray from inside the character
// it is also good to note that the transform position in the sample
assets is at the base of the character
if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector
3.down, out hitInfo, m_GroundCheckDistance))
{
m_GroundNormal = hitInfo.normal;
m_IsGrounded = true;
m_Animator.applyRootMotion = true;
}
else
{
m_IsGrounded = false;
m_GroundNormal = Vector3.up;
m_Animator.applyRootMotion = false;
}
}}}}

Rigid Body First Person Control:


using System;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
namespace UnityStandardAssets.Characters.FirstPerson
{
[RequireComponent(typeof (Rigidbody))]
[RequireComponent(typeof (CapsuleCollider))]
public class RigidbodyFirstPersonController : MonoBehaviour
{
[Serializable]
public class MovementSettings
{
public float ForwardSpeed = 8.0f; // Speed when walking forward
public float BackwardSpeed = 4.0f; // Speed when walking backwa
rds
public float StrafeSpeed = 4.0f; // Speed when walking sideways
public float RunMultiplier = 2.0f; // Speed when sprinting
public KeyCode RunKey = KeyCode.LeftShift;
public float JumpForce = 30f;
public AnimationCurve SlopeCurveModifier = new AnimationCurve(
new Keyframe(-90.0f, 1.0f), new Keyframe(0.0f, 1.0f), new Keyfram

e(90.0f, 0.0f));
[HideInInspector] public float CurrentTargetSpeed = 8f;
#if !MOBILE_INPUT
private bool m_Running;
#endif
public void UpdateDesiredTargetSpeed(Vector2 input)
{
if (input == Vector2.zero) return;
if (input.x > 0 || input.x < 0)
{
//strafe
CurrentTargetSpeed = StrafeSpeed;
}
if (input.y < 0)
{
//backwards
CurrentTargetSpeed = BackwardSpeed;
}
if (input.y > 0)
{
//forwards
//handled last as if strafing and moving forward at the same ti
me forwards speed should take precedence
CurrentTargetSpeed = ForwardSpeed;
}
#if !MOBILE_INPUT
if (Input.GetKey(RunKey))
{
CurrentTargetSpeed *= RunMultiplier;
m_Running = true;
}
else
{
m_Running = false;
}
#endif
}
#if !MOBILE_INPUT
public bool Running
{
get { return m_Running; }
}
#endif
}

[Serializable]
public class AdvancedSettings
{
public float groundCheckDistance = 0.01f; // distance for checking
if the controller is grounded ( 0.01f seems to work best for this )
public float stickToGroundHelperDistance = 0.5f; // stops the chara
cter
public float slowDownRate = 20f; // rate at which the controller co
mes to a stop when there is no input
public bool airControl; // can the user control the direction that is b
eing moved in the air
[Tooltip("set it to 0.1 or more if you get stuck in wall")]
public float shellOffset; //reduce the radius by that ratio to avoid g
etting stuck in wall (a value of 0.1f is nice)
}
public Camera cam;
public MovementSettings movementSettings = new MovementSettin
gs();
public MouseLook mouseLook = new MouseLook();
public AdvancedSettings advancedSettings = new AdvancedSettings(
);
private
private
private
private
private

Rigidbody m_RigidBody;
CapsuleCollider m_Capsule;
float m_YRotation;
Vector3 m_GroundContactNormal;
bool m_Jump, m_PreviouslyGrounded, m_Jumping, m_IsGroun

ded;
public Vector3 Velocity
{
get { return m_RigidBody.velocity; }
}
public bool Grounded
{
get { return m_IsGrounded; }
}
public bool Jumping
{
get { return m_Jumping; }
}
public bool Running

{
get
{
#if !MOBILE_INPUT
return movementSettings.Running;
#else
return false;
#endif
}
}
private void Start()
{
m_RigidBody = GetComponent<Rigidbody>();
m_Capsule = GetComponent<CapsuleCollider>();
mouseLook.Init (transform, cam.transform);
}
private void Update()
{
RotateView();
if (CrossPlatformInputManager.GetButtonDown("Jump") && !
m_Jump)
{
m_Jump = true;
}
}
private void FixedUpdate()
{
GroundCheck();
Vector2 input = GetInput();
if ((Mathf.Abs(input.x) > float.Epsilon || Mathf.Abs(input.y) > float.
Epsilon) && (advancedSettings.airControl || m_IsGrounded))
{
// always move along the camera forward as it is the direction th
at it being aimed at
Vector3 desiredMove = cam.transform.forward*input.y + cam.tr
ansform.right*input.x;
desiredMove = Vector3.ProjectOnPlane(desiredMove, m_Ground
ContactNormal).normalized;
desiredMove.x = desiredMove.x*movementSettings.CurrentTarg
etSpeed;

desiredMove.z = desiredMove.z*movementSettings.CurrentTarg
etSpeed;
desiredMove.y = desiredMove.y*movementSettings.CurrentTarg
etSpeed;
if (m_RigidBody.velocity.sqrMagnitude <
(movementSettings.CurrentTargetSpeed*movementSettings.C
urrentTargetSpeed))
{
m_RigidBody.AddForce(desiredMove*SlopeMultiplier(), ForceM
ode.Impulse);
}
}
if (m_IsGrounded)
{
m_RigidBody.drag = 5f;
if (m_Jump)
{
m_RigidBody.drag = 0f;
m_RigidBody.velocity = new Vector3(m_RigidBody.velocity.x,
0f, m_RigidBody.velocity.z);
m_RigidBody.AddForce(new Vector3(0f, movementSettings.Ju
mpForce, 0f), ForceMode.Impulse);
m_Jumping = true;
}
if (!m_Jumping && Mathf.Abs(input.x) < float.Epsilon && Math
f.Abs(input.y) < float.Epsilon && m_RigidBody.velocity.magnitude < 1f)
{
m_RigidBody.Sleep();
}
}
else
{
m_RigidBody.drag = 0f;
if (m_PreviouslyGrounded && !m_Jumping)
{
StickToGroundHelper();
}
}
m_Jump = false;
}
private float SlopeMultiplier()
{
float angle = Vector3.Angle(m_GroundContactNormal, Vector3.up);
return movementSettings.SlopeCurveModifier.Evaluate(angle);

}
private void StickToGroundHelper()
{
RaycastHit hitInfo;
if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f
- advancedSettings.shellOffset), Vector3.down, out hitInfo,
((m_Capsule.height/2f) - m_Capsule.radius) +
advancedSettings.stickToGroundHelperDistance, ~0,
QueryTriggerInteraction.Ignore))
{
if (Mathf.Abs(Vector3.Angle(hitInfo.normal, Vector3.up)) < 85f)
{
m_RigidBody.velocity = Vector3.ProjectOnPlane(m_RigidBody.
velocity, hitInfo.normal);
}
}
}
private Vector2 GetInput()
{
Vector2 input = new Vector2
{
x = CrossPlatformInputManager.GetAxis("Horizontal"),
y = CrossPlatformInputManager.GetAxis("Vertical")
};
movementSettings.UpdateDesiredTargetSpeed(input);
return input;
}
private void RotateView()
{
//avoids the mouse looking if the game is effectively paused
if (Mathf.Abs(Time.timeScale) < float.Epsilon) return;
// get the rotation before it's changed
float oldYRotation = transform.eulerAngles.y;
mouseLook.LookRotation (transform, cam.transform);
if (m_IsGrounded || advancedSettings.airControl)
{
// Rotate the rigidbody velocity to match the new direction that t
he character is looking
Quaternion velRotation = Quaternion.AngleAxis(transform.euler

Angles.y - oldYRotation, Vector3.up);


m_RigidBody.velocity = velRotation*m_RigidBody.velocity;
}
}
/// sphere cast down just beyond the bottom of the capsule to see if t
he capsule is colliding round the bottom
private void GroundCheck()
{
m_PreviouslyGrounded = m_IsGrounded;
RaycastHit hitInfo;
if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f
- advancedSettings.shellOffset), Vector3.down, out hitInfo,
((m_Capsule.height/2f) - m_Capsule.radius) + advan
cedSettings.groundCheckDistance, ~0, QueryTriggerInteraction.Ignore))
{
m_IsGrounded = true;
m_GroundContactNormal = hitInfo.normal;
}
else
{
m_IsGrounded = false;
m_GroundContactNormal = Vector3.up;
}
if (!m_PreviouslyGrounded && m_IsGrounded && m_Jumping)
{
m_Jumping = false;
}
}
}
}

Menu Module:
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class MenuObject : MonoBehaviour
{
public bool isQuit = false;
public Renderer rend;
void start(){
rend.GetComponent<Renderer> ();
}
void OnMouseEnter()
{
rend.material.color = Color.red;

}
void OnMouseExit()
{
rend.material.color= Color.black;
}
void OnMouseDown()
{
if (isQuit){
Application.Quit();
}
else
{
SceneManager.LoadScene(1);
rend.material.color= Color.white;
}
}}

Scene1
topview of the design of the Central
maze--

Room1--Contains different colored cubes


and a hidden coin behind any one of these.

Room2--Contains, a nature look terrain with


non-uniform surface and trees, pond, a coin
hidden in the water.

Room3-Room3 design is of a castle .


FrontView of castle

slight-Tilted side view

Inside the castle--

charchter movement during gameview

coin Collection and time Calculation scripts


have been enabled as well.

Scripts
For Rotating Coins during playmode.
using UnityEngine;
using System.Collections;
using System.Threading;
public class PickUp : MonoBehaviour {

void Update () {
transform.Rotate (new Vector3 (0, 360,0 )
*Time.deltaTime);

}
}

For disabling COins when player walks through it and COunting


and displaying its value.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class CharachterController : MonoBehaviour {
public Text CountText;
private int count;
void Start(){
count = 0;
SetCountValue();
}
void OnTriggerEnter(Collider other){
if (other.gameObject.CompareTag ("pick up")) {
other.gameObject.SetActive (false);
count = count + 1;
SetCountValue();
}
}
void SetCountValue(){
CountText.text = "coins: " + count.ToString();
}
}

TimeController

using
using
using
using
using
using

UnityEngine;
UnityEngine.UI;
System.Collections;
System.Globalization;
System.Threading;
System;

public class TimeController : MonoBehaviour {


public Text timeText;
private float t;
// Use this for initialization
void Start () {
t= 60;
}
// Update is called once per frame
void Update () {
t-= Time.deltaTime;
if(t>0)
{
timeText.text = "Time: " + t.ToString();
}
For Animating the doors and enabling the BOx-Collider when
player comes in contact
using
using
using
using

UnityEngine;
System.Collections;
System;
UnityStandardAssets.Utility;

public class doors : MonoBehaviour {


Animator animator;
bool DoorOpen;
void Start(){

DoorOpen = false;
animator = GetComponent<Animator> ();
}
void OnTriggerEnter(Collider other){
if (other.gameObject.tag == "Player") {
DoorOpen = true;
door ("Open");
}
}
void OnTriggerExit(Collider other)
{
if (DoorOpen) {
DoorOpen = false;
door ("Close");
}
}
void door(String direction)
{
animator.SetTrigger(direction);
}
}

Das könnte Ihnen auch gefallen