Sign in to follow this  

Unity Third person camera with free look

This topic is 664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have been trying to implement a third person camera syste: m in Unity, but not based on the default system. My goal is something more like Unreal Engine system, used also in Mass Effect or The Witcher 2/3. This system provides a camera free look, and then the character moves towards the camera direction.

My current approach consists of having a pivot GameObject, that follows the playecr GameObject. The pivot handles camera free look and other things like selecting objects in front of the camera (which right no, is not working well), and the crosshair (totally missing):

public class PivotControl : MonoBehaviour {
	float rotationY = 0F;
	Camera cam;
	Text label;

	// Use this for initialization
	void Start () {
		cam = gameObject.GetComponentInChildren<Camera> ();
		label = GameObject.Find ("Label").GetComponent<Text>();;
	}
	
	// Update is called once per frame
	void Update () {		
		if (Input.GetAxis ("Mouse X") != 0 || Input.GetAxis ("Mouse Y") != 0) {
			
			float rotationX = gameObject.transform.localEulerAngles.y + Input.GetAxis("Mouse X") * 2f;

			rotationY += Input.GetAxis("Mouse Y") * 5f;		
			gameObject.transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
			cam.transform.LookAt(cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane)));
			RaycastHit hit;					
			Ray ray =  cam.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
			if (Physics.Raycast (ray, out hit, 100)) {
					 
				if (hit.collider.tag=="Interactable")
					label.text = "Press E to interact with "+hit.collider.name;
			} else {
				label.text = "";
			}
		}
	}
}

The player script handles character movement and I have noticed that the rotatio towards camera direction works fine for small angles, when the difference between the player direction and the camera direction is not too large:

public class PlayerControl : MonoBehaviour {

	public GameObject pivot;
	Animator anim;
	int direction = 0;
	int FORWARD  = 1;
	int BACKWARD = 2;
	int LEFT = 3;
	int RIGHT = 4;

	// Use this for initialization
	void Start () {
		//cam = gameObject.GetComponent<Camera> ();
		//Cursor.visible = false;
		//Cursor.lockState = CursorLockMode.Locked;
		anim = gameObject.GetComponent<Animator> ();
	}
	
	// Update is called once per frame
	void Update () {
		Vector3 rot;

		if (Input.GetKeyDown (KeyCode.W)) {
			direction = FORWARD;
		} else if (Input.GetKeyDown (KeyCode.S)) {
			//go back
			direction = BACKWARD;
		} else if (Input.GetKeyDown (KeyCode.A)) {
			direction = LEFT;
		} else if (Input.GetKeyDown (KeyCode.D)) {
			direction = RIGHT;
		} else if (Input.GetKeyUp (KeyCode.W) || Input.GetKeyUp (KeyCode.S) || Input.GetKeyUp (KeyCode.A) || Input.GetKeyUp (KeyCode.D)) {
			direction = 0;
		}

		switch (direction) {
			case 0: //do nothing
				anim.SetInteger("State",0);
				break;
			case 1:		//forward
				rot = gameObject.transform.localEulerAngles;
				rot.y = pivot.transform.localEulerAngles.y;
				gameObject.transform.rotation = Quaternion.Slerp (gameObject.transform.rotation, Quaternion.Euler (rot), 5f * Time.deltaTime);
				anim.SetInteger("State",1);
				gameObject.transform.Translate (0, 0, 20 * Time.deltaTime);				
			pivot.transform.position = Vector3.Slerp(pivot.transform.position, gameObject.transform.position, 5f *Time.deltaTime);
				break;
			case 2: //
				rot = gameObject.transform.localEulerAngles;
				rot.y = pivot.transform.localEulerAngles.y+180f;
				gameObject.transform.rotation = Quaternion.Slerp (gameObject.transform.rotation, Quaternion.Euler (rot), 5f * Time.deltaTime);
				anim.SetInteger("State",1);
				gameObject.transform.Translate (0, 0, 20 * Time.deltaTime);
				pivot.transform.position = Vector3.Slerp(pivot.transform.position, gameObject.transform.position, 5f *Time.deltaTime);
				break;
			case 3:
				rot = gameObject.transform.localEulerAngles;
				rot.y = pivot.transform.localEulerAngles.y-90f;
				gameObject.transform.rotation = Quaternion.Slerp (gameObject.transform.rotation, Quaternion.Euler (rot), 5f * Time.deltaTime);
				anim.SetInteger("State",1);
				gameObject.transform.Translate (0, 0, 20 * Time.deltaTime);
				pivot.transform.position = Vector3.Slerp(pivot.transform.position, gameObject.transform.position, 5f *Time.deltaTime);
			break;
			case 4:
				rot = gameObject.transform.localEulerAngles;
				rot.y = pivot.transform.localEulerAngles.y+90f;
				gameObject.transform.rotation = Quaternion.Slerp (gameObject.transform.rotation, Quaternion.Euler (rot), 5f * Time.deltaTime);
				anim.SetInteger("State",1);
				gameObject.transform.Translate (0, 0, 20 * Time.deltaTime);				
				pivot.transform.position = Vector3.Slerp(pivot.transform.position, gameObject.transform.position, 5f *Time.deltaTime);
			break;
		}
	}
}

Can somebody, please, suggest some improvements for this code? Im specially interested in solving the selection problem and implementing the crosshair.

 

Share this post


Link to post
Share on other sites

I would break out the label and code for interactive object checking into a different component, they aren't really related to a third person camera look.  You could easily do the raycasting from the camera in another component attached to the same object.  It'll keep things cleaner, and more re-usable.

 

Your movement code is odd.  I would avoid looking at keys, and look at input controls.  That would make it trivial to swap to using WASD or a twin stick controller.   I'd also set the a vertical & horizontal movement axis separately, your else ifs block holding both W and A, for example.  Granted it's been ages since I've played a Mass Effect, so maybe that's by design.  Rather than switching off direction and rotating, you could project the camera's forward and right(or left) vectors onto a 2d plane, and then scale those by the vertical and horizontal movement axis to move camera relative.

 

Some Nits:

Be consistent, if you are setting Direction as LEFT, RIGHT, etc, use LEFT, RIGHT in your switch-case, not 0, 1, 2, 3.  If you're not checking for null or asserting, you should probably stick a [requirecomponent] trait on your classes for the things you require to exist.  Try not to stick magic numbers in your code, add some [serializefield] floats for those vertical and horiztonal look axis scalars.

 

EDIT:  For selection, I think I would do it in two stages, I would get all the interactive objects that are within X distance to the player, get rid of any the camera is not facing (dot check), and if it's only one, then I would show that one.  If there is more than one, I would create a line from the camera, do a distance-line check, and take the closest one.  That makes it less fiddly for the player, if they're standing in the elevator, they probably want to activate it.  If they are near multiple corpses, or are standing in the elevator but there is a dead corpse to loot, if they're looking close to the corpse, they probably want to loot it.  (You'll notice that exact same logic would work for a first person game too -- and strengthens my argument for ripping it out into it's own component)

Edited by ferrous

Share this post


Link to post
Share on other sites

This topic is 664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      628653
    • Total Posts
      2984050
  • Similar Content

    • By arash khalaqhdoust
      hey guys i hope you doing all well. last night i released my first game in google app store, i really appreciate you guys  to download it. and share your reviews about it
      the idea of game comes from mini hackgame of Bioshock.
       link of download:
      https://play.google.com/store/apps/details?id=com.RVBinary.piperist
      many thanks
    • By ForgedInteractive
      Who We Are
      We are Forged Interactive, a small team of like-minded game developers with the sole purpose of making games we love! Currently, we're progressing very quickly with our first project and there are plenty of opportunities and work for new interested programmers. With this project, our development platform is Unity 5.5.2 and C# as our behavioral language. Since this project is our first release, the game itself is a smaller project though progress is moving quickly. We are looking to finalize the current project and get started on future projects in the near future and are expanding our team to do so.
       
      Who We Are Looking For:
      Programmer Level Designer  
      About the Game
      Ours is the tale of two siblings, thrown into a world of chaos. Living in the shadow of their parents' heroic deeds and their Uncle's colorful military career, Finn and Atia are about to become the next force to shape our world. How will you rise through the ranks of Hereilla and what will be your legacy? Once defeated your enemies turn coat and join you in your adventures. Players can enjoy a range of troops and abilities based on their gameplay style which become more important as maps introduce more challenging terrain, enemies and bosses. Strong orc knights, dangerous shamans, and even a dragon are out on the prowl. Knowing when to fight and when to run, and how to manage your army is essential. Your actions alone decide the fate of this world.
       
      Previous Work by Team
      Although we are working towards our first game as Forged Interactive, our team members themselves have worked on titles including and not limited to:
      Final Fantasy Kingsglaive FIFA 2017 Xcom 2 Civilization  
      What do we expect?
      Reference work or portfolio. Examples what have you already done and what projects you have worked on academic or otherwise. The ability to commit to the project on a regular basis. If you are going on a two-week trip, we don't mind, but it would be good if you could commit 10+ hours to the project each week. Willingness to work with a royalty based compensation model, you will be paid when the game launches. Openness to learning new tools and techniques
       
      What can we offer?
      Continuous support and availability from our side. You have the ability to give design input, and creative say in the development of the game. Shown in credits on websites, in-game and more. Insight and contacts from within the Industry.
       
      Contact
      If you are interested in knowing more or joining, please email or PM us on Skype. A member of our management team will reply to you within 48 hours.
       
      E-mail: Recruitment@ForgedInteractive.com
      Skype: ForgedInteractive
       
      Regards,
      David, Colin and Joseph
       
      Follow us on:
      Facebook: https://www.facebook.com/ForgedInteractive/
      Twitter: @ForgedInteract
      Youtube: https://www.youtube.com/channel/UCpK3zhq5ToOeDpdI0Eik-Ug?view_as=subscriber
      Reddit: www.reddit.com/user/Forged_Interactive

    • By dell96
      I'm trying to make my first project but I'm stuck i don't know how to make my crate to start to spawn again when i hit the start button after i die.
      hoping someone can help!!!
      Crate.cs
      CrateSpawn.cs
      Cratework.cs
      GameController.cs
      GameManager.cs
  • Popular Now