une camera style google Earth

Pour les scripts écrits en C#
Règles du forum
Merci de respecter la NOMENCLATURE suivante pour vos TITRES de messages :

Commencez par le niveau de vos scripts
DB = Débutant
MY = Moyen
CF = Confirmé

Puis le domaine d'application
-RS = Réseau
-AL = Algorithmie

Exemple :

[DB-RS] Mouvement perso multijoueur
obefa
Messages : 32
Inscription : 24 Fév 2012 11:43
Localisation : Paris
Contact :

une camera style google Earth

Message par obefa » 12 Juin 2015 13:09

Bonjour,

je souhaiterais créer un système de navigation style google earth, ou assez proche.
J'utilise la script sur le wiki pour gérer la caméra "MouseOrbitZoom" qui me convient plutôt bien : http://wiki.unity3d.com/index.php/MouseOrbitZoom
Je n'arrive pas cependant à gérer le système de collision de la caméra avec son environnement. Je lui ai ajouté une sphère collider et un rigidbody. Ce qui n'a aucun effet. La caméra passe à travers mon terrain... Une idée de la procédure à adopter ?

merci pour votre aide :)

Avatar de l’utilisateur
xaralec
Messages : 13
Inscription : 11 Juin 2015 22:57
Localisation : Canada

Re: une camera style google Earth

Message par xaralec » 12 Juin 2015 18:33

créer une sphère ensuite met un sphère collider sur ta sphère et glisse celle -ci su ta camera dans ta hierarchy ensuite la position de ta sphère a zero et finalement met la invisible. Oublie pas de mettre ta sphère de la même taille que ta camera pour pousser le réalisme.

De cette manière c'est comme ci ta camera était solide. puisque quelle est attaché a la sphère qui est solide.

C'est juste une idée comme ça mais je crois que ça pourrait fonctionner.

obefa
Messages : 32
Inscription : 24 Fév 2012 11:43
Localisation : Paris
Contact :

Re: une camera style google Earth

Message par obefa » 15 Juin 2015 15:02

Merci pour ta réponse. J'avais déjà essayé cette méthode mais malheureusement cela ne fonctionne pas... une autre idée ?

sotec
Messages : 542
Inscription : 21 Sep 2012 10:11

Re: une camera style google Earth

Message par sotec » 15 Juin 2015 15:14

tu peux lancer un raycasthit en direction du sol, et si la distance de collision est inférieur ou égale à une valeur X tu empèche la caméra de descendre plus bas

Mais le principe du collider devrait marcher ><
┬─┬ノ(º - ºノ) - (╯°□°)╯︵ ┻━┻

obefa
Messages : 32
Inscription : 24 Fév 2012 11:43
Localisation : Paris
Contact :

Re: une camera style google Earth

Message par obefa » 15 Juin 2015 15:42

J'ai l'impression que le raycast utiliserait plus de ressources qu'un simple collider, non ?
Donc si le principe du collider pouvait fonctionner cela m’arrangerait bien... J'ai testé en mettant des simples murs mais la caméra passe toujours au travers, étrange non ??

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 5385
Inscription : 28 Avr 2014 11:57
Localisation : Toulouse

Re: une camera style google Earth

Message par boubouk50 » 15 Juin 2015 16:16

Non, tu dois surement mal t'y prendre ou oublier quelque chose. Les collisions marchent, c'est une évidence.
Peux-tu nous décrire exactement ce que tu as mis en place?
Il ne suffit pas d'ajouter des colliders à tous les GameObjects pour que les collisions marchent.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Avatar de l’utilisateur
Titan
Messages : 582
Inscription : 12 Sep 2011 13:54
Contact :

Re: une camera style google Earth

Message par Titan » 15 Juin 2015 16:16

Ton script ne doit pas modifier directement le transform mais les fonctions du rigidbody si tu veux appliquer des collisions.Il faut que tu modifie ton script "MouseOrbitZoom"
____________________________________________
Hop Boy

obefa
Messages : 32
Inscription : 24 Fév 2012 11:43
Localisation : Paris
Contact :

Re: une camera style google Earth

Message par obefa » 15 Juin 2015 16:22

Alors, j'ai mise en place une caméra, sur laquelle le script suivant est attaché :

Code : Tout sélectionner

//
//Filename: maxCamera.cs
//
// original: http://www.unifycommunity.com/wiki/index.php?title=MouseOrbitZoom
//
// --01-18-2010 - create temporary target, if none supplied at start
 
using UnityEngine;
using System.Collections;
 
 
[AddComponentMenu("Camera-Control/3dsMax Camera Style")]
public class maxCamera : MonoBehaviour
{
    public Transform target;
    public Vector3 targetOffset;
    public float distance = 5.0f;
    public float maxDistance = 20;
    public float minDistance = .6f;
    public float xSpeed = 200.0f;
    public float ySpeed = 200.0f;
    public int yMinLimit = -80;
    public int yMaxLimit = 80;
    public int zoomRate = 40;
    public float panSpeed = 0.3f;
    public float zoomDampening = 5.0f;
 
    private float xDeg = 0.0f;
    private float yDeg = 0.0f;
    private float currentDistance;
    private float desiredDistance;
    private Quaternion currentRotation;
    private Quaternion desiredRotation;
    private Quaternion rotation;
    private Vector3 position;
 
    void Start() { Init(); }
    void OnEnable() { Init(); }
 
    public void Init()
    {
        //If there is no target, create a temporary target at 'distance' from the cameras current viewpoint
        if (!target)
        {
            GameObject go = new GameObject("Cam Target");
            go.transform.position = transform.position + (transform.forward * distance);
            target = go.transform;
        }
 
        distance = Vector3.Distance(transform.position, target.position);
        currentDistance = distance;
        desiredDistance = distance;
 
        //be sure to grab the current rotations as starting points.
        position = transform.position;
        rotation = transform.rotation;
        currentRotation = transform.rotation;
        desiredRotation = transform.rotation;
 
        xDeg = Vector3.Angle(Vector3.right, transform.right );
        yDeg = Vector3.Angle(Vector3.up, transform.up );
    }
 
    /*
     * Camera logic on LateUpdate to only update after all character movement logic has been handled. 
     */
    void LateUpdate()
    {
        // If Control and Alt and Middle button? ZOOM!
        if (Input.GetMouseButton(2) && Input.GetKey(KeyCode.LeftAlt) && Input.GetKey(KeyCode.LeftControl))
        {
            desiredDistance -= Input.GetAxis("Mouse Y") * Time.deltaTime * zoomRate*0.125f * Mathf.Abs(desiredDistance);
        }
        // If middle mouse and left alt are selected? ORBIT
        else if (Input.GetMouseButton(2) && Input.GetKey(KeyCode.LeftAlt))
        {
            xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
            yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
 
            ////////OrbitAngle
 
            //Clamp the vertical axis for the orbit
            yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
            // set camera rotation 
            desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
            currentRotation = transform.rotation;
 
            rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
            transform.rotation = rotation;
        }
        // otherwise if middle mouse is selected, we pan by way of transforming the target in screenspace
        else if (Input.GetMouseButton(2))
        {
            //grab the rotation of the camera so we can move in a psuedo local XY space
            target.rotation = transform.rotation;
            target.Translate(Vector3.right * -Input.GetAxis("Mouse X") * panSpeed);
            target.Translate(transform.up * -Input.GetAxis("Mouse Y") * panSpeed, Space.World);
        }
 
        ////////Orbit Position
 
        // affect the desired Zoom distance if we roll the scrollwheel
        desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
        //clamp the zoom min/max
        desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
        // For smoothing of the zoom, lerp distance
        currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
 
        // calculate position based on the new currentDistance 
        position = target.position - (rotation * Vector3.forward * currentDistance + targetOffset);
        transform.position = position;
    }
 
    private static float ClampAngle(float angle, float min, float max)
    {
        if (angle < -360)
            angle += 360;
        if (angle > 360)
            angle -= 360;
        return Mathf.Clamp(angle, min, max);
    }
}
J'ai attaché une sphère avec un collider à la caméra.

Mes terrains ont leur collider par défaut.

obefa
Messages : 32
Inscription : 24 Fév 2012 11:43
Localisation : Paris
Contact :

Re: une camera style google Earth

Message par obefa » 15 Juin 2015 16:45

ok donc générer le script avec la modification du rigidbody...

Une petite aide par ou commencer ? car passer d'une modif de transform à rigibody ça ne me parait pas évident comme ça...

EDIT : je test des choses et je reviendrais vers vous si j'ai des soucis !

obefa
Messages : 32
Inscription : 24 Fév 2012 11:43
Localisation : Paris
Contact :

Re: une camera style google Earth

Message par obefa » 15 Juin 2015 17:46

Alors voilà où j'en suis : J'ai essayé de traduire les transform en rigidbody du type GetComponent<Rigidbody>().position de déplacer la caméra avec MovePosition et de même pour la rotation. J'ai ajouté une sphère collider et un rigidbody à ma caméra en freezant les rotations (x, y, z) dans les contraintes (pour éviter l'effet toupie) avec l'interpolation sur "interpolate".
Tout fonctionne comme auparavant mais un peu trop justement, je n'ai toujours pas de collision avec mon terrain... :(

Voici le code modifié :

Code : Tout sélectionner

using UnityEngine;
using System.Collections;

public class MaxCameraRigidBody : MonoBehaviour {

	public static Transform TARGET;
	public Vector3 targetOffset;
	public float distance = 5.0f;
	public float maxDistance = 20;
	public float minDistance = .6f;
	public float xSpeed = 200.0f;
	public float ySpeed = 200.0f;
	public int yMinLimit = -80;
	public int yMaxLimit = 80;
	public int zoomRate = 40;
	public float panSpeed = 0.3f;
	public float zoomDampening = 5.0f;
	
	private float xDeg = 0.0f;
	private float yDeg = 0.0f;
	public float currentDistance;
	private float desiredDistance;
	private Quaternion currentRotation;
	private Quaternion desiredRotation;
	public static Quaternion rotation;
	private Vector3 position;
	
	public Texture2D cursorTextureOrbit;
	public Texture2D cursorTexturePan;
	private CursorMode cursorMode = CursorMode.Auto;
	private Vector2 hotSpot = Vector2.zero;

	private Rigidbody rb; 
	
	
	void Start() {
		Init(); }
	
	void OnEnable() { Init(); }
	
	public void Init()
	{

		rb = GetComponent<Rigidbody>(); // on chope le rigibody de la caméra

		//If there is no target, create a temporary target at 'distance' from the cameras current viewpoint
		if (!TARGET)
		{
			GameObject go = new GameObject("Cam_Target");
			go.transform.position = rb.position + (transform.forward * distance);
			TARGET = go.transform;
		}
		
		
		distance = Vector3.Distance(transform.position, TARGET.position);
		currentDistance = distance;
		desiredDistance = distance;
		
		//be sure to grab the current rotations as starting points.
		position = rb.position;
		rotation = rb.rotation;
		currentRotation = rb.rotation;
		desiredRotation = rb.rotation;
		
		xDeg = Vector3.Angle(Vector3.right, transform.right );
		yDeg = Vector3.Angle(Vector3.up, transform.up );
	}
	
	/*
     * Camera logic on LateUpdate to only update after all character movement logic has been handled. 
     */
	void LateUpdate()
	{
		
		
		// If Control and Alt and Middle button? ZOOM!
		if (Input.GetMouseButton(2) && Input.GetKey(KeyCode.LeftAlt) && Input.GetKey(KeyCode.LeftControl))
		{
			desiredDistance -= Input.GetAxis("Mouse Y") * Time.deltaTime * zoomRate*0.125f * Mathf.Abs(desiredDistance);
			RaycastHit hit;
			if (Physics.Linecast (TARGET.position, rb.position, out hit)) 
			{
				desiredDistance -=  hit.distance;
				print ("distance=" + desiredDistance);
			}
		}
		// If middle mouse and left alt are selected? ORBIT
		//else if (Input.GetMouseButton(2) && Input.GetKey(KeyCode.LeftAlt))
		else if (Input.GetButton("Fire2"))  // -> bouton droit pour orbit
		{
			
			
			Cursor.SetCursor(cursorTextureOrbit, hotSpot, cursorMode);
			
			xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
			yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
			
			////////OrbitAngle
			
			//Clamp the vertical axis for the orbit
			yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
			// set camera rotation 
			desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
			currentRotation = rb.rotation;
			
			rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
			//rb.rotation = rotation;
			rb.MoveRotation (rotation);
			
			
		}
		// otherwise if middle mouse is selected, we pan by way of transforming the TARGET in screenspace
		else if (Input.GetMouseButton(2))  // -> mollette souris
			//else if (Input.GetButton("Fire1"))  // -> bouton gauche souris pour le pan
			
		{
			
			Cursor.SetCursor(cursorTexturePan, hotSpot, cursorMode);
			
			//grab the rotation of the camera so we can move in a psuedo local XY space
			TARGET.rotation = rb.rotation;
			TARGET.Translate(Vector3.right * -Input.GetAxis("Mouse X") * panSpeed);
			TARGET.Translate(transform.up * -Input.GetAxis("Mouse Y") * panSpeed, Space.World);
			
		} else if (!Input.GetButton("Fire2")) 
			
		{
			
			Cursor.SetCursor(null, Vector2.zero, cursorMode); // on rétabli le cursor normal
			
			
		} else if (!Input.GetMouseButton(2)) 
			
		{
			
			Cursor.SetCursor(null, Vector2.zero, cursorMode); // on rétabli le cursor normal
			
			
		}


		////////ZOOM MOLETTE
				
		// affect the desired Zoom distance if we roll the scrollwheel
		desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
		//clamp the zoom min/max
		desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
		// For smoothing of the zoom, lerp distance
		currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
		
		// calculate position based on the new currentDistance 
		position = TARGET.position - (rotation * Vector3.forward * currentDistance + targetOffset);
		rb.MovePosition (position);
		//rb.position = position;
	}
	
	private static float ClampAngle(float angle, float min, float max)
	{
		if (angle < -360)
			angle += 360;
		if (angle > 360)
			angle -= 360;
		return Mathf.Clamp(angle, min, max);
	}
}
Ce n'est pas la bonne méthode n'est-ce pas ..?

Répondre

Revenir vers « (C#) CSharp »