Page 1 sur 2
[RESOLU] Velo qui suit une pente
Publié : 20 Jan 2022 11:27
par freepl
Bonjour
J'ai fait un vélo et il doit monter une pente. Il suit bien le path mais son pivot est au centre. La roue avant est sous la route et la roue arrière survole la route.
- ScreenShot020.jpg (259.27 Kio) Consulté 1913 fois
Ici le pivot est bien sur la chaussée.
- ScreenShot021.jpg (143.09 Kio) Consulté 1913 fois
Je pense que c'est au niveau de la gravité mais j'ai un doute.
- ScreenShot022.jpg (66.14 Kio) Consulté 1913 fois
comment faire pour que le vélo suive réellement la pente du path ?
Merci
Re: Velo qui suit une pente
Publié : 20 Jan 2022 14:03
par boubouk50
Comment est-il animé?
Est-ce via l'Animator? Est ce par script? Est-ce le RigidBody qui est déplacé? Comment?
En gros, si l'animation bloque l'orientation alors tu ne peux pas l'aligner via le rigidbody.
Une solution pourrait être de récupérer la normale du sol au point de contact pour aligner le vélo dessus (solution simple)
Sinon, il faut 2 colliders, 1 au niveau de chaque roue et revoir la physique pour que les deux touches le sol. Mais la physique, ce n'est pas mon domaine.
Re: Velo qui suit une pente
Publié : 20 Jan 2022 14:54
par freepl
Bonjour
Il est animé via un script basé sur ITWEEN et je pense que c'est bien l'animation qui bloque l'orientation.
Peux tu m'expliquer la solution de récupérer la normale du sol au point de contact pour aligner le vélo dessus.
Code : Tout sélectionner
using UnityEngine;
using System.Collections;
using System;
// donne le% de véhicules
[Serializable]
public struct Trajets {
public GameObject trajet;
public float vitesse;
public float mEntrePoint;
public DepartVl[] departVl;
}
[Serializable]
public struct DepartVl {
public int positionDepart;
public float vitesseDepart;
}
public enum InterieurVl {
None,
Oui,
Non
}
public class DebutRoute : MonoBehaviour {
// script qui detruit le vl à la fin du parcours et l'instancie au départ
// si true coché = début si false non coché = à fin
/*Donc tu choisie dans l'inspector le nombre de vl que tu veux au lancement de ta maquette pour chaque trajet et le programme vas te les instancié automatiquement par rapport à la fraction et au trajet.
example :
ligne Vl depart 4 , car j'ai 4 voies
element 0 : 4 si je veux 4 vl affichés dès le lancement de la maquette sur cette voie
element 1 : 1 si je veux 1 vl affichés dès le lancement de la maquette sur cette voie
element 2 : 3 si je veux 3 vl affichés dès le lancement de la maquette sur cette voie
element 3 : 10 si je veux 10 vl affichés dès le lancement de la maquette sur cette voie
Pour element0 , on a mis 0. Il y aura 0 véhicuke sur le trajet à 0.0, 0.25, 0.5 et 0.75
Pour element3 , on a mis 10. Il y aura 10 véhicuke sur le trajet à 0,0. 0.1, 0.2, 0.3, ....., 0.9
Il n'y a acucun vl à 1 car il serait à la fin du trajet et donc invisible !
*/
public Trajets[] trajets;
private int choixTrajet;
// pour multiplier le temps d'apparition des vl la nuit
public float multiplicateurNuit = 1.0f;
// temps apparition entre chaque voiture choisi au hasard
public float[] tempsApparition; // dans inspector donner le nombre de temsp puis les renseigner
//choisis un temps aléatoire
private int choixTemps;
private float temps;
public float pCar;
public float pUtilitaire;
public float pSemi;
public float pBus;
public float SpSemiLong;
public float pMoto;
private int choixPourcentage;
private bool finStart;
private Light jourNuit;
void Start () {
choixTemps = UnityEngine.Random.Range(0,tempsApparition.Length);
choixTrajet = UnityEngine.Random.Range(0,trajets.Length);
choixPourcentage = UnityEngine.Random.Range(1,101);
if (pCar + pUtilitaire + pSemi + pBus + SpSemiLong + pMoto > 100)
Debug.LogError("il y a plus de 100%");
if (pCar + pUtilitaire + pSemi + pBus + SpSemiLong + pMoto < 100)
Debug.LogError("il y a moin de 100%");
for (int i = 0; i < trajets.Length; i++) {
CreationVlDepart (i);
}
// 1 ° gamobject car seul dans la hierarchy.on va chercher sky Dome
// je prends son enfant Light
// dans Inspector on prend Light
jourNuit = GameObject.Find("Sky Dome").transform.FindChild("Light").GetComponent<Light>();
finStart = true;
}
// Update is called once per frame
void Update () {
if (finStart && Time.timeScale != 0) {
temps += Time.fixedDeltaTime;
// on multiplie le temps d'apparition si light < à 0.15
float tempsTempoApparition = 0.0f;
if ( jourNuit.intensity < 0.15f) {
tempsTempoApparition = tempsApparition[choixTemps] * multiplicateurNuit;
}
else {
tempsTempoApparition = tempsApparition[choixTemps];
}
//automatiquement
if (temps >= tempsTempoApparition) {
CreationVl(trajets[choixTrajet].trajet, trajets[choixTrajet].mEntrePoint, trajets[choixTrajet].vitesse, 0);
choixTemps = UnityEngine.Random.Range(0,tempsApparition.Length);
choixTrajet = UnityEngine.Random.Range(0,trajets.Length);
choixPourcentage = UnityEngine.Random.Range(1,101);
temps = 0;
}
}
}
void CreationVlDepart (int countTrajet) {
if (trajets[countTrajet].departVl.Length != 0) {
for (int i = 0; i < trajets[countTrajet].departVl.Length; i++) {
CreationVl (trajets[countTrajet].trajet, trajets[countTrajet].mEntrePoint, trajets[countTrajet].departVl[i].vitesseDepart, trajets[countTrajet].departVl[i].positionDepart);
}
}
}
public void CreationVl (GameObject trajet, float metre, float vitesseFraction, int position) {
string nom = "";
int choixVl = 0;
InterieurVl interieur = InterieurVl.None;
//voitures
if (choixPourcentage < pCar) {
choixVl = UnityEngine.Random.Range(1,19); //19car il y a 18 voitures + 1
nom = "Voitures/Car_";
interieur = InterieurVl.Oui;
//utilitaires
} else if (choixPourcentage < pCar + pUtilitaire) {
choixVl = UnityEngine.Random.Range(1,14);//14 car il y a 13 utilitaires+ 1
nom = "Utilitaires/utilitaire_";
interieur = InterieurVl.Oui;
//semi
} else if (choixPourcentage < pCar + pUtilitaire + pSemi) {
choixVl = UnityEngine.Random.Range(1,9);//car 8 camions ne pas prendre les porte char et le double remoque
nom = "Poids_Lourds/semi_";
interieur = InterieurVl.Oui;
//bus
} else if (choixPourcentage < pCar + pUtilitaire + pSemi + pBus) {
choixVl = UnityEngine.Random.Range(1,4);//car 3 bus +1
nom = "BUS/bus_";
interieur = InterieurVl.Oui;
//semi long 2 remorque et porte char
} else if (choixPourcentage < pCar + pUtilitaire + pSemi+ pBus + SpSemiLong) {
choixVl = UnityEngine.Random.Range(1,4);//car 2 porte chars et le double remoque
nom = "Super_Poids_Lourds_Longs/semiLong_";
interieur = InterieurVl.Oui;
//moto
} else if (choixPourcentage <= pCar + pUtilitaire + pSemi+ pBus + SpSemiLong + pMoto) {
choixVl = UnityEngine.Random.Range(1,9);//9
nom = "Motos/moto_";
interieur = InterieurVl.Non;
}
GameObject instance = Instantiate(Resources.Load(""+nom+choixVl,typeof(GameObject))) as GameObject;
//modif du non
instance.name += trajet.name;
//change la postion de l'object dans le scéne
//donc transform = à l'obejct qui contient le script DebutRoute
instance.transform.SetParent(transform);
if (GetComponent<TrajetVl>() != null) {
//set le parcour sur l'object
instance.GetComponent<TrajetVl>().target_Path = trajet;
//modif la vitesse de l'object
instance.GetComponent<TrajetVl>().kmh = vitesseFraction;
instance.GetComponent<TrajetVl>().kmhActuel = vitesseFraction;
instance.GetComponent<TrajetVl>().minTab = position;
instance.GetComponent<TrajetVl>().mEntrePoint = metre;
instance.GetComponent<TrajetVl>().interieur = interieur;
instance.GetComponent<TrajetVl>().DemrageVl();
} else {
//set le parcour sur l'object
instance.GetComponentInChildren<TrajetVl>().target_Path = trajet;
//modif la vitesse de l'object
instance.GetComponentInChildren<TrajetVl>().kmh = vitesseFraction;
instance.GetComponentInChildren<TrajetVl>().kmhActuel = vitesseFraction;
instance.GetComponentInChildren<TrajetVl>().minTab = position;
instance.GetComponentInChildren<TrajetVl>().mEntrePoint = metre;
instance.GetComponentInChildren<TrajetVl>().interieur = interieur;
instance.GetComponentInChildren<TrajetVl>().DemrageVl();
}
}
}
Merci
Re: Velo qui suit une pente
Publié : 20 Jan 2022 14:57
par boubouk50
Tu balances un Raycast vers le bas depuis ton vélo et tu récupères la normale du hit. Tu alignes ensuite ton vélo a ce vecteur.
Re: Velo qui suit une pente
Publié : 21 Jan 2022 11:23
par freepl
Bonjour
Mon modèle de base :
un empty avec le script de déplacement , un box collider , et rigidbody sans gravity . le groupe vélo est en enfant
Modèle fonctionnel:
un empty avec le script de déplacement
le groupe vélo Rigidbody avec gravity et Freeze rotation sur Y et Z ( Mass 0.01, drag 0, Angle drag 0.05, collision detection Discrete)
les 2 roues avec mesh collider + convex
- ScreenShot026.jpg (192.32 Kio) Consulté 1823 fois
Comment est-il possible d'optimiser la consommation de ressources ?
Merci Boubouk
Edit : Quelle est la différence entre Convexe et Smooth sphere collisions ainsi que la répercussion sur la gestion des ressources ?
Re: Velo qui suit une pente
Publié : 21 Jan 2022 14:02
par boubouk50
Pour ce qu'il y ait de la physique, je ne saurai te répondre. La documentation devrait te le dire.
Concernant, l'optimisation, ne pas passer par la physique serait bien plus performant. Si tu fais un Tween, tu devrais je pense pouvoir aligner correctement ton vélo rien qu'avec celui-ci.
Ton path définit un vecteur directionnel qu'il affecte à ton pivot de vélo. Il définit donc un plan orthogonal dont il est la normale Z. Sur ce plan XY, il suffit de prendre n'importe quel vecteur dont Y est différent de 0 et de mettre X à 0 (et de le normaliser: c'est ton vecteur vertical normal au sol.
Si ça se trouve le Tween te donne déjà cette orientation sans avoir à la calculer. En fait c'est un LookAt () que tu fais.
[ RESOLU] : Velo qui suit une pente
Publié : 21 Jan 2022 15:19
par freepl
Effectivement avec la physique mes fps passe de 60 ) 10 images/sec
Du coup je vais rester sur mon système
ITween aligne bien mon objet sur XY mais sur le plan vertical il semble plus lent .
voici le code complet
Code : Tout sélectionner
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
// la fonction de trajet aérien est bloquée
public class TrajetVl : MonoBehaviour {
public GameObject target_Path;
public float kmh; // vitesse voulue
public float kmhActuel; // vitesse reelle
public float mEntrePoint = 5.0f;
private float time;
public float fraction;
public Transform[] tabtList = new Transform[11];
public int minTab = 0;
public Transform detecteur;
public LayerMask layerPanneau;
public Collider[] toucheDetecteur;
public bool coupeDetecteur;
private Light jourNuit;
private GameObject eclairage;
private GameObject eclairageFreins;
public GameObject clignotantsDroits;
public GameObject clignotantsGauche;
private IEnumerator coroutineClignotants;
public InterieurVl interieur;
public void DemrageVl () {
tabtList = new Transform[11];
TabDynamique ();
if (transform.FindChild("Detecteur"))
detecteur = transform.FindChild("Detecteur").transform;
jourNuit = GameObject.Find("Sky Dome").transform.FindChild("Light").GetComponent<Light>();
//cherche dans ces enfants un object avec le nom Eclairage
//si existe alors on ajoute l'object portant le nom "Eclairage" dans la variable eclairage
if (this.transform.FindChild ("Eclairage")) {
eclairage = this.transform.FindChild ("Eclairage").gameObject;
}
if (this.transform.FindChild ("Eclairage_Freins")) {
eclairageFreins = this.transform.FindChild ("Eclairage_Freins").gameObject;
eclairageFreins.SetActive (false);
}
if (this.transform.FindChild ("Eclairage_Clignotants_droits")) {
clignotantsDroits = this.transform.FindChild ("Eclairage_Clignotants_droits").gameObject;
clignotantsDroits.SetActive (false);
}
if (this.transform.FindChild ("Eclairage_Clignotants_gauche")) {
clignotantsGauche = this.transform.FindChild ("Eclairage_Clignotants_gauche").gameObject;
clignotantsGauche.SetActive (false);
}
StartCoroutine("WalkThePath");
}
public void TabDynamique () {
fraction = 0.1f;
int count = 0;
for (int i = 0; i < 11; i++) {
if (minTab+i < target_Path.transform.childCount) {
tabtList[i] = target_Path.transform.GetChild(minTab+i);
count++;
}
}
if (minTab+8 < target_Path.transform.childCount)
minTab += 8;
else
minTab += count;
}
public void StopCoroutine () {
StopCoroutine("WalkThePath");
}
IEnumerator WalkThePath () {
while(true){
time = (tabtList.Length * mEntrePoint)/(kmhActuel / 3.6f);
transform.position = iTween.PointOnPath (tabtList, fraction);
fraction += Time.deltaTime / time;
if (fraction > 1.0f)
fraction = 0.0f;
/* modif pour vehicule ou personnage*/
if (gameObject.tag == "VEHICULE")
{
transform.LookAt(iTween.PointOnPath(tabtList, fraction + 0.05f)); // fraction + 0.1f
}
else
{
Vector3 direction =iTween.PointOnPath(tabtList, fraction + 0.05f);//fraction + 0.1f
direction.y = this.transform.position.y;
transform.LookAt(direction);
}
if (kmhActuel < kmh){
kmhActuel += 0.7f;// acceleration jusqu'à la vitesse kmh 0.7f
} else if (kmhActuel > kmh && kmh != 0) {
kmhActuel -= 0.9f;// decceleration douce 0.9
} else if (kmh == 0) {
kmhActuel = 0;// on stoppe brutalement le VL
}
if (fraction >= 0.9f) //0.9f
TabDynamique();
GestionDetecteur ();
GestionLumiere ();
GestionFreins ();
yield return null;
}
}
void GestionDetecteur () {
if (detecteur != null) {
if (gameObject.tag == "VEHICULE")
toucheDetecteur = Physics.OverlapSphere(detecteur.position, 0.75f, layerPanneau);
else
toucheDetecteur = Physics.OverlapSphere(detecteur.position, 0.5f, layerPanneau);
if (toucheDetecteur.Length != 0) {
foreach (var other in toucheDetecteur) {
if (other.tag == "CoupeDetecteur") {
coupeDetecteur = other.GetComponent<CoupeDetecteur>().detecteur;
kmhActuel = 50.0f;// pour degager les croisements
}
if (other.tag == "CoupeDetecteurAutre") {
coupeDetecteur = other.GetComponent<CoupeDetecteur>().detecteur;
kmhActuel = 4.0f;
}
if (coupeDetecteur == false) {
if (other.tag == "ModifVitesse") {
kmh = other.GetComponent<Panneau>().vitesse;
} else if (other.tag == "EntreeInstersection") {
kmh = other.GetComponent<Priorite>().vitesse;
} else if (other.tag == "VEHICULE") {
if (kmh > other.GetComponent<TrajetVl>().kmh)
kmh = other.GetComponent<TrajetVl>().kmh;
} else if (other.tag == "ClignotantsOn") {
kmh = other.GetComponent<GestionClignotants>().vitesse;
if (other.GetComponent<GestionClignotants>().trajet == target_Path) {
ClignotantsOff ();
if (other.GetComponent<GestionClignotants>().enumClignotants == EnumClignotants.Droites) {
coroutineClignotants = ClignotantsDroits();
StartCoroutine (coroutineClignotants);
} else {
coroutineClignotants = ClignotantsGauche();
StartCoroutine (coroutineClignotants);
}
}
} else if (other.tag == "ClignotantsOff") {
kmh = other.GetComponent<GestionClignotants>().vitesse;
ClignotantsOff ();
}
}
}
}
if (kmhActuel == 0 && toucheDetecteur.Length == 0)
kmhActuel = 30.0f;
}
}
void GestionLumiere () {
if (eclairage != null) {
if (jourNuit.intensity < 0.15f) {
if (eclairage.activeInHierarchy == false)
eclairage.SetActive (true);
}
else {
if (eclairage.activeInHierarchy == true)
eclairage.SetActive (false);
}
}
}
void GestionFreins () {
if (eclairageFreins != null){
if (kmhActuel > kmh+3 || kmhActuel == 0) {
if (eclairageFreins.activeInHierarchy == false)
eclairageFreins.SetActive (true);
} else {
if (eclairageFreins.activeInHierarchy == true)
eclairageFreins.SetActive (false);
}
}
}
IEnumerator ClignotantsDroits () {
if (clignotantsDroits != null) {
while (true) {
clignotantsDroits.SetActive (true);
yield return new WaitForSeconds (0.3f);
clignotantsDroits.SetActive (false);
yield return new WaitForSeconds (0.3f);
}
}
}
IEnumerator ClignotantsGauche () {
if (clignotantsGauche != null) {
while (true) {
clignotantsGauche.SetActive (true);
yield return new WaitForSeconds (0.3f);
clignotantsGauche.SetActive (false);
yield return new WaitForSeconds (0.3f);
}
}
}
void ClignotantsOff () {
if (coroutineClignotants != null) {
StopCoroutine (coroutineClignotants);
if (clignotantsDroits != null)
clignotantsDroits.SetActive (false);
if (clignotantsGauche != null)
clignotantsGauche.SetActive (false);
coroutineClignotants = null;
}
}
}
C'est ici que le script définit le chemin mais et je ne vois pas comment le modifier , je n'ai que la vraible 0.05f que je peux modifier.
Code : Tout sélectionner
IEnumerator WalkThePath () {
while(true){
time = (tabtList.Length * mEntrePoint)/(kmhActuel / 3.6f);
transform.position = iTween.PointOnPath (tabtList, fraction);
fraction += Time.deltaTime / time;
if (fraction > 1.0f)
fraction = 0.0f;
/* modif pour vehicule ou personnage*/
if (gameObject.tag == "VEHICULE")
{
transform.LookAt(iTween.PointOnPath(tabtList, fraction + 0.05f)); // fraction + 0.1f
}
else
{
Vector3 direction =iTween.PointOnPath(tabtList, fraction + 0.05f);//fraction + 0.1f
direction.y = this.transform.position.y;
transform.LookAt(direction);
}
"Sur ce plan XY, il suffit de prendre n'importe quel vecteur dont Y est différent de 0 et de mettre X à 0 (et de le normaliser: c'est ton vecteur vertical normal au sol." Tu fais ça comment ( juste le principe) ?
Merci Je marque en résolu quand même
Re: Velo qui suit une pente
Publié : 31 Jan 2022 16:09
par boubouk50
boubouk50 a écrit : ↑21 Jan 2022 14:02
Si ça se trouve le Tween te donne déjà cette orientation sans avoir à la calculer. En fait c'est un LookAt () que tu fais.
Code : Tout sélectionner
transform.LookAt(iTween.PointOnPath(tabtList, fraction + 0.05f)); // fraction + 0.1f
Tu fais bien un LookAt (), sauf que tu ne précises pas le vector3
worldUp (voir
Documentation LookAt ()) et c'est cela que tu dois stipuler.
Comme dit, peut-être iTween le donne sinon tu peux faire un Raycast vers le bas et récupérer le vecteur normal du Hit sur le sol.
Ce qui me taraude, c'est que le LookAt () sur le prochain transform, devrait déjà aligner le vélo correctement sur le Up, mais pas sur le Right (considérant que le Forward est la direction Avant du vélo).
Ton vélo, est-il bien tagué VEHICULE??
Re: Velo qui suit une pente
Publié : 01 Fév 2022 13:25
par freepl
Bonjour
Désolé pour la réponse tardive
En épluchant le code j'ai vu qu'il fallait un tag particulier VEHICUEL pour s'orienter. J'ai donc ajouté le tag VELO au script et cela fonctionne.
Code : Tout sélectionner
/* modif pour vehicule ou personnage*/
if (gameObject.tag == "VEHICULE")
{
transform.LookAt(iTween.PointOnPath(tabtList, fraction + 0.08f)); //0.05F plus c'est petit est plus de tremblote pour s'orienter sur le point à 0.005m
}
else
{
Vector3 direction =iTween.PointOnPath(tabtList, fraction + 0.08f); //0.05F
direction.y = this.transform.position.y;
transform.LookAt(direction);
}
if (gameObject.tag == "VELO")
{
transform.LookAt(iTween.PointOnPath(tabtList, fraction + 0.08f)); //0.05F plus c'est petit est plus de tremblote pour s'orienter sur le point à 0.005m
}
else
{
Vector3 direction =iTween.PointOnPath(tabtList, fraction + 0.08f); //0.05F
direction.y = this.transform.position.y;
transform.LookAt(direction);
}
Le vélo suit bien le terrain
- Z019.jpg (361.8 Kio) Consulté 1702 fois
Merci du coup de main
Re: [RESOLU] Velo qui suit une pente
Publié : 01 Fév 2022 16:56
par boubouk50
Au lieu de créer un nouveau Tag et de dupliquer le code, tu pourrais tout simplement utiliser le tag VEHICULE sur le vélo. Ou bien l'insérer directement dans la condition
Code : Tout sélectionner
if (gameObject.tag == "VEHICULE" || gameObject.tag == "VELO")
{
transform.LookAt(iTween.PointOnPath(tabtList, fraction + 0.08f)); //0.05F plus c'est petit est plus de tremblote pour s'orienter sur le point à 0.005m
}
else //PIETONS
{
Vector3 direction =iTween.PointOnPath(tabtList, fraction + 0.08f); //0.05F
direction.y = this.transform.position.y;
transform.LookAt(direction);
}