La variable n'est pas assignée dans l'inspector d'Unity. Peut être que tu as plusieurs gameobjects avec le même script et sur un des objets ce n'est pas renseigné
Bien vu! Merci beaucoup! J'avais effectivement le script assigné à un objet et a un de ses enfants ( erreur de ma part).
Merci !!
Hello tout le monde !
Alors voila j'ai passé l'aprèm à développer un système de saut dans un environnement 2D.
dans mon système de saut je veux:
c'est sur ce dernier point que je bloque je vous partage mon code:
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
Rigidbody2D rb2d;
public float speed;
float horizontal = 0f;
public float jumpForce;
bool canDoubleJump = false;
bool canDoubleJump2;
private float jumpTimeCounter;
public float jumpTime;
bool isJumping;
bool isJumping2;
private bool isGrounded;
public Transform feetPos;
public float checkRadius;
public LayerMask whatIsGround;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
horizontal = Input.GetAxis("Horizontal");
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
// move left right
transform.Translate(Vector2.right * Time.deltaTime * speed * horizontal);
//jump and double jump:
//double jump without first jump ( when player fall from a platform )
if (isGrounded == false && canDoubleJump2 == true)
{
doubleJump();
}
//double jump
if (canDoubleJump == true)
{
doubleJump();
}
//first jump
else
{
firstJump();
}
//is grounded verification
if (isGrounded == true)
{
canDoubleJump2 = true;
}
// double jump function
void doubleJump()
{
if (Input.GetButtonDown("Jump") )
{
isJumping = true;
jumpTimeCounter = jumpTime;
rb2d.velocity = Vector2.up * jumpForce;
}
if (Input.GetButton("Jump") && isJumping == true)
{
if (jumpTimeCounter > 0)
{
rb2d.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetButtonUp("Jump"))
{
isJumping = false;
canDoubleJump = false;
canDoubleJump2 = false;
}
}
// first jump function
void firstJump()
{
if (Input.GetButtonDown("Jump") && isGrounded == true )
{
canDoubleJump2 = false;
isJumping2 = true;
isJumping = true;
jumpTimeCounter = jumpTime;
rb2d.velocity = Vector2.up * jumpForce;
}
if (Input.GetButton("Jump") && isJumping == true && isJumping2 == true)
{
if (jumpTimeCounter > 0)
{
rb2d.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetButtonUp("Jump") && isJumping2 ==true)
{
isJumping2 = false;
isJumping = false;
canDoubleJump = true;
}
}
}
}
Je pense que le problème vient de mon "isGrounded" qui est une zone sous mon personnage.
Mon système prévoit que quand j'effectue le premier saut, "canDoubleJump2" devient false mais à la frame d'après, je refais une vérification "isGrounded" et malgré que le personnage est déjà entrain de sauter, il est trop proche du sol et "canDoubleJump2" passe true, ce qui crée un conflit entre mes deux fonctions ( "firstJump" et "doubleJump" ) et qui foire le premier saut ( qui n'est plus contrôlable) .
avez vous une parade à ce problème?
Merci d'avance et désolé pour le pavé, j'espère que j'ai été assez claire et que c'est pas trop le bordel dans mon script.
Associes VS a unity et mets des breakpoints sur les points importants.
ensuite f10 / f11 pour voir ou ca coince, quitte a faire une frame complete instruction par instruction.
sinon ce genre de synthaxe sert pas a grand chose :
if (isGrounded == false && canDoubleJump2 == true)
{
doubleJump();
}
par exemple ca suffit :
if (!isGrounded && canDoubleJump2) doubleJump();
Quand le programme grossi ca simplifie la vie.
J'ai testé ton code cabalarial01, mais il fonctionne bien ! Est-ce que tu peux être plus précis sur le problème ?
Il faudrait peut-être améliorer tes conditions pour ne pas appeler 2 fois la methode DoubleJump, mais je pense pas que ton soucis vienne de la.
if((!isGrounded && canDoubleJump2) || canDoubleJump) {
DoubleJump();
} else {
FirstJump();
}
Avec ton code j'ai découvert qu'on peut imbriquer des fonctions, on en apprends tous les jours
Le 27 février 2021 à 13:07:49 Geoffroypir a écrit :
Associes VS a unity et mets des breakpoints sur les points importants.
ensuite f10 / f11 pour voir ou ca coince, quitte a faire une frame complete instruction par instruction.
J'ai pas saisie ce que tu appels breakpoint ( je crois que Unity est déjà associé)
sinon ce genre de synthaxe sert pas a grand chose :
if (isGrounded == false && canDoubleJump2 == true)
{
doubleJump();
}par exemple ca suffit :
if (!isGrounded && canDoubleJump2) doubleJump();Quand le programme grossi ca simplifie la vie.
Ca par contre c'est super cool ! J'ai regardé énormément de tutos et aucun ne présentait les choses comme ça. Aujourd'hui j'ai ajouté des trucs et je passe trop de temps a scorller parce que je cherche une ligne etc...
merci du conseil !
Le 27 février 2021 à 19:42:37 IssaBarbier a écrit :
J'ai testé ton code cabalarial01, mais il fonctionne bien ! Est-ce que tu peux être plus précis sur le problème ?Il faudrait peut-être améliorer tes conditions pour ne pas appeler 2 fois la methode DoubleJump, mais je pense pas que ton soucis vienne de la.
if((!isGrounded && canDoubleJump2) || canDoubleJump) { DoubleJump(); } else { FirstJump(); }
Avec ton code j'ai découvert qu'on peut imbriquer des fonctions, on en apprends tous les jours
Apres une bonne nuit de sommeil j'ai réussi à trouver: Il fallait effectivement que j'améliore mes conditions !
J'en profite pour vous poser une dernière question: on est d'accord, j'ai foiré ma balise code? j'ai pas réussi à l'utiliser correctement et j'ai toujours pas compris comment ça marche.
Désolé pour le double post, mais j'ai trouvé ce qui cause le problème.
Effectivement il y avait un conflit entre le premier saut et le double saut (après tomber). La modification que j'ai présenter au dessus m'as permis de m'en rendre plus facilement compte.
En révisant l'ordre des conditions et en les adaptant un peu tu devrais avoir le comportement voulu :
//first jump
if (isGrounded || isJumping2) // on ajout la condition pour savoir s'il peut sauter ou s'il est en cours de saut
{
firstJump();
}
//double jump
else if (canDoubleJump || canDoubleJump2) // s'il n'est pas au sol ni en train d'effectuer le premier saut mais peut faire un double saut.
{
doubleJump();
}
Il y a peut-être moyen de combiner canDoubleJump et canDoubleJump2 mais je te laisse voir pour ça
(Si pas de ligne vide avant la balise ça marche pas apparemment)
ça m'arche pas très bien
Ok alors les breakpoints c'est un peu le Graal quand tu commence à te plonger dans la programmation, et ca t'évites énormément de mal de tête. Je te rassure c'est tout con, pourtant je le vois jamais dans les tutos sur internet.
Suffit de cliquer sur la marge a gauche du code la ou tu veux que le programme s'arrête. (ta un rond rouge qui s'affichera)
En gros quand VS est associé à unity (attached) ben la programme va stopper a cet endroit, ensuite si tu clique sur "continue" le programme exécutera jusqu'au prochain breakpoint. Ou bien tu appuis sur f10 (pour aller a l'instruction suivante) ou F11 pour aller en profondeur dans les les fonctions appelées.
Mais le mieux est que tu peux ajouter des condition dans tes breakpoints, pour que le programme s'arrete seulement quand tu cherche une situation particulière.
Pour de très gros programmes avec des centaines de millier ou des millions de lignes, je peux te dire que ca va t'aider. Et pour les petits programmes debugger sera bien plus facile.
Autre conseil, c'est super de commenter ton code mais la c'est carrément redondant, tu nommes très bien tes fonctions et tes variables alors pas besoin de mettre des truc genre :
//first jump
firstJump();
et si tu veux décrire ta fonction tu mets ca directement en haut de la définition de ta fonction genre
//description
void FirstJump()
{
blabla
}
Je suis plutôt novice sur unity mais tu serais pas en train de faire un translate sur un rigidbody ?
transform.Translate(Vector2.right * Time.deltaTime * speed * horizontal);
Evites de faire ca comme la peste :
1- c'est extrement lent (xperience perso sur ca c'est AFFREUSEMENT lent) car en gros tu actualises toute ta hierarchie de collider (yikes!)
2-ben en gros tu téléportes ton objet, ignorant tout ce qu(il y a entre. Pas idéal pour les collisions. et parfait pour passer au travers des trucs.
utilise ca : https://docs.unity3d.com/ScriptReference/Rigidbody-position.html
ou mieux ca : https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html
Parcontre garde quand même en réserve la technique de tartinage de lignes, il y a des boites qui évaluent les developpeur par le nombre de lignes qu'ils écrivent .
(je déconne même pas)
sérieux ?
Sinon j'avais utilisé transform.translate parce que je ne comprenais pas très bien les autres méthode aujourd'hui j'ai mis en place un système de dash et les animations d'idle, run, de jump et de fall, tout marche nickel comme je le souhaite ( à part le double jump qui a un raté une fois sur 10 j'arrive pas à comprendre pourquoi ) et je voulais commencer à me pencher sur un système d'ennemis et d'attaque. Mais je crois que je vais plutôt suivre tes conseils et revoir mon système de déplacement et faire le ménage dans mon script
Merci de vos réponses en tout cas! J'apprends tellement de choses !
Et mets tout ca dans un fixedupdate plutôt qu'un update. sinon la vitesse du jeu va dépendre de la puissance de l'ordi en gros.
Ps : à ton service
à part le double jump qui a un raté une fois sur 10 j'arrive pas à comprendre pourquoi
Ah oui alors ca pu le translate qui passe au travers de ton collider. essais avec moveposition ou quelquechose qui applique une force.
J'essaye ça demain ! Pareil pour le FixedUpdate mais il me semble que je l'avais déjà mis et que plus rien ne marchait
J'ai mis tout ça dans mon FixedUpdate et plus rien ne marche, je ne comprends pas pourquoi
Salut,
J'ai une fonction de soin qui est appelée toutes les x secondes, quand un perso entre dans une zone (et donc au on trigger enter, je lance une coroutine pour se soigner toutes les x secondes
private IEnumerator Heal(IHealable healable)
{
yield return new WaitForSeconds(frequency);
while (healable != null)
{
healable.Heal(heal);
yield return new WaitForSeconds(frequency);
}
}
Mais parfois ça plante car ça appelle la ligne healable.Heal() et ça me met l'erreur :
MissingReferenceException: The object of type 'HealeableUnit' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
et ça me montre la ligne "healable.Heal(heal)"
Je comprend pas je fais bien la vérification avant pourtant ?
Vous avez une idée ? je comprend ptet pas bien le fonctionnement des IEnumerator ?
Quand un UnityEngine.Object est détruit, il ne disparait pas de la mémoire tant qu'il y a une référence qui pointe vers lui. Il n'est donc pas null. L'opérateur "==" de UnityEngine.Object reverra cependant true quand un objet détruit est comparé avec null. Mais l'opérateur "==" de System.Object renverra false dans la même situation. Comme ici tu utilises une interface c'est ce dernier qui est appelé.
Si j'ai juste il suffit de remplacer ta condition par :
while(healable as UnityEngine.Object)
Si tu as des IHealable qui ne sont pas des UnityEngine.Object il te faudra trouver une autre solution.
Il te faut 2 scripts : un pour l'arme dans la scène, avec une fonction OnTriggerEnter, et un pour l'arme dans le Canvas, avec une fonction pour activer l'image.
Pour afficher/cacher une Image c'est bien Behaviour.enabled ou GameObject.SetActive qu'il faut appeler. Le premier active l'Image, et le second le GameObject en entier (donc ça désactive/active les scripts attachés à cet objet aussi). Je ne comprends pas ou tu bloques avec ça, le seul truc auquel il faut penser c'est de désactiver l'objet dans l'éditeur ou au début du jeu (dans la fonction Start ou Awake).
La seule difficulté c'est la communication entre les deux scripts. FindObjectOfType est sans doute le plus simple mais il vaut mieux prendre l'habitude de ne pas l'utiliser car c'est une fonction très peu performante (même si ici ça ne devrais pas poser de problème). Une autre façon de faire c'est d'utiliser une variable "static" (pattern singleton) :
public class GunCollectible : MonoBehaviour{
OnTrigger(var col){
//Ajouter ici une condition pour vérifier que c'est bien le joueur qui a trigger
GunImage.Instance.Display();
}
}
[RequireComponent(typeof(Image))]
public class GunImage{
public static Instance;
private Image Image;
private void Awake(){
Instance = this;
Image = GetComponent<Image>();
Image.enabled = false;
}
public void Display(){ Image.enabled = true; }
}
Regarde un tuto sur le pattern singleton, mon code est simplifié et pas propre.
La meilleure solution pour ce genre de trucs c'est d'utiliser un événement, mais bien gérer ses événements n'est pas ce qu'il y a de plus simple quand on débute.
Le 28 février 2021 à 22:55:34 ThetaTauTau a écrit :
Quand un UnityEngine.Object est détruit, il ne disparait pas de la mémoire tant qu'il y a une référence qui pointe vers lui. Il n'est donc pas null. L'opérateur "==" de UnityEngine.Object reverra cependant true quand un objet détruit est comparé avec null. Mais l'opérateur "==" de System.Object renverra false dans la même situation. Comme ici tu utilises une interface c'est ce dernier qui est appelé.Si j'ai juste il suffit de remplacer ta condition par :
while(healable as UnityEngine.Object)
Si tu as des IHealable qui ne sont pas des UnityEngine.Object il te faudra trouver une autre solution.
Bordel c'est ça
ça marche maintenant
ça fait des mois que je cherche en fait je pensais pas que quelqu'un me répondrait et aussi vite
Merci !
Je savais que unity faisait quelqu'un chose de spécial avec les == null, mais je savais pas que la comparaison pouvait changer en fonction de comment l'objet est casté c'est un peu bizarre comme comportement
Donc si je fais des interfaces implémentées par des UnityEngine.Object et que je veux voir si l'objet existe encore dans le jeu faut que je le case avant de vérifier s'il est null ?
Je crois que je suis parti pour revérifier tout mon code du coup encore merci
Grosse subtilité du c#, je risque plus de l'oublier
Bonjour, j'ai commencé à coder sous Unity avant-hier et il y a quelque chose que je ne comprends pas.
private GameObject[] xp_go;
private void SetLevel()
{
/*
des if modifiant des variables sans importance
*/
Debug.Log("oui");
xp_go = GameObject.FindGameObjectsWithTag("xp"); // <---- le script s'arrête ici
Debug.Log("non");
foreach (GameObject xpgo in xp_go) {
RectTransform rt = xpgo.GetComponent(typeof(RectTransform)) as RectTransform;
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 100);
rt.ForceUpdateRectTransforms();
}
}
Comme indiqué dans le commentaire, le script s'arrête brutalement.
Quelqu'un saurait me dire d'où ça peut venir ?
Est-ce qu'il y a une erreur ? Est-ce qu'il y a un GameObject avec le tag "xp" ?