FANDOM


Si vous avez bien suivit les précédentes étapes de ce tutoriel, vous devriez avoir un début de jeu, avec un menu et une scène contenant un objet pouvant être déplacé dans les 4 directions. Vous devriez également savoir comment gérer la souris et les autres inputs, déplacer les objets… autant dire l’essentiel !

Orienter notre personnageModifier

L’objectif de cette partie va être d’orienter notre objet en direction de la souris.

La première chose à faire, est donc de déterminer le point vers lequel orienter notre objet. Souvenez vous que nous somme dans un espace 3D alors que la souris se déplace dans un espace en 2D (l’écran), mais nous avons déjà résolu ce genre de problème dans le tutoriel précédent, grâce à un ray et à la fonction IntersectModelRenderer() pour savoir si le curseur étais sur le model de notre bouton.

Nous allons utiliser le même genre de technique ici. On va lancer un rayon depuis notre caméra, passant par le pointeur et chercher son intersection avec le sol, ce qui nous donnera le point vers lequel orienter notre objet.

Comme d’habitude, toutes les méthodes des ray sont définies ici : Référence Scripting/Ray. Nous allons utiliser :

[number ou nil] Ray:IntersectsPlane( [Plane] plan )

Commençons par créer notre rayon à partir de notre caméra. On défini une variable publique dans le Awake() pour stocker le composant Camera de notre objet Camera :

self.cameraComponent = CraftStudio.FindGameObject( "Camera" ):GetComponent( "Camera" )

Puis dans le Update(), on récupére la position de la souris et on crée notre ray :

local mousePos = CraftStudio.Input.GetMousePosition()
local mouseRay = self.cameraComponent:CreateRay( mousePos )

Il ne nous manque plus que l’argument à passer à notre function mouseRay:IntersectsPlane(). Celui ci doit être un plan. Les plans, comme les vecteurs, sont des objets mathématiques (ils n’ont donc pas de représentation à l’écran). D’après la référence (Référence Scripting/Plane), un plan est créé par :

[Plane] Plane:New( [Vector3] normal, [number] distance )

Notre plan sera ici tous les points ayant la même coordonnée Y=-1. Le vecteur normal sera donc le vecteur Y (0,1,0), que l’on peu créer directement avec Vector3:Up(). On défini donc notre plan dans le Awake() avec :

self.groundPlane = Plane:New( Vector3:Up(), -1 )

Et notre fonction de recherche d’intersection s’écrit donc :

local distance = mouseRay:IntersectsPlane( self.groundPlane )

A partir de cette distance et des propriétés de notre ray, on peut facilement calculer le point d’intersection avec :

local targetPos = mouseRay.position + mouseRay.direction * distance

Attention, si il n’y a pas d’intersection entre notre plan et notre ray, distance vaudra nil ce qui pourrais générer des érreurs. Pour y remédier, on place toute les lignes qui utilisent distance dans un if :

if distance ~= nil then
   local targetPos = mouseRay.position + mouseRay.direction * distance
end

Si vous voulez vérifier que notre point est bien calculé, créez un viseur en ajoutant un objet dans vore scène (un simple cube peut faire l’affaire) puis ajoutez :

self.viseur = CraftStudio.FindGameObject( "viseur" ) -- dans le Awake()

self.viseur.transform:SetPosition( targetPos ) -- dans le dernier if

Lancez votre scène et normalement, votre viseur doit suivre le pointeur de la souris. Vous pouvez ajuster sa hauteur en modifiant la définition de self.groundPlane.

Il ne reste plus qu’a orienter notre objet vers sa cible avec :

self.gameObject.transform:LookAt( targetPos )

En testant vous devriez vous rendre compte que l’ensemble est difficilement contrôlable. En effet la caméra étant liée à notre objet, elle tourne en même temps que lui. Dans votre scène, commencez donc par désassocier la caméra de l’objet. Ensuite, avec tout ce que vous avez appris jusqu'à présent, vous devriez être capable de créer un script simple permettant à votre caméra de suivre votre objet. Script complet :

function Behavior:Awake()
   self.vitesse = 0.05
   self.groundPlane = Plane:New( Vector3:Up(), -1 )
   self.cameraComponent = CraftStudio.FindGameObject( "Camera" ):GetComponent( "Camera" )

   self.viseur = CraftStudio.FindGameObject( "viseur" ) -- optionel
end

function Behavior:Update()
   --gestion des déplacements
   local horizontal = CraftStudio.Input.GetAxisValue( "Horizontal" )
   local vertical = CraftStudio.Input.GetAxisValue( "Vertical" )

   local mouvement = Vector3:New( horizontal, 0, -vertical )
   mouvement = mouvement * self.vitesse

   self.gameObject.transform:Move( mouvement )

   --gestion de l'orientation
   local mousePos = CraftStudio.Input.GetMousePosition()
   local mouseRay = self.cameraComponent:CreateRay( mousePos )
   local distance = mouseRay:IntersectsPlane( self.groundPlane )

   if distance ~= nil then
       local targetPos = mouseRay.position + mouseRay.direction * distance
       self.viseur.transform:SetPosition( targetPos ) -- optionnel
       self.gameObject.transform:LookAt( targetPos )
   end
end

Tirer des projectilesModifier

​Maintenant nous allons permettre à notre objet de lancer des projectiles.


Dans notre script commençons par définir à quel moment les projectiles serons créés : lors d’un clic de la souris. Par défaut, le clic gauche est lié à l’input Fire (vous pouvez vérifier dans les propriétés de votre projet) Dans le Update() on ajoute donc une nouvelle condition :

if CraftStudio.Input.IsButtonDown( "Fire" ) then
 --
end

Il nous reste à savoir quoi mettre dans notre condition pour créer notre projectile ! La technique la plus simple est de définir notre projectile dans une nouvelle scène préfabriquée. Ensuite, depuis notre script dans la scène principale on va ajouter (« instancier ») un nouvel objet créé à partir de notre scène préfabriquée. On pourra créer autant de nouveaux objet que l’on veut, qui serons tous indépendants et tous des copies de l’objet contenu dans la scène préfabriquée.

Commencez donc par créer le model de votre projectile (un petit cube de couleur par exemple), puis créez une nouvelle scène. Nommez-la "prefab_bullet". Le préfixe « prefab_ » servira à différencier vos scènes de jeu et les scènes servant à définir des éléments préfabriqués. Dans cette scène, ajouter un objet auquel vous associez votre model et un nouveaux script (nommé « bullet » par exemple). Ce script définira le comportement de notre projectile.

Pour le moment nous souhaitons simplement qu’il avance tous droit. Nous allons utiliser la méthode transform:MoveOriented() afin d’être sûr qu’il se déplace toujours droit devant lui. On obtient:

function Behavior:Awake()
   self.speed = 0.5
end

function Behavior:Update()
   self.gameObject.transform:MoveOriented( Vector3:Forward()*self.speed ) 
end

Maintenant dans le script qui gère notre personnage, ajoutons une ligne qui créera un nouvel objet construit à partir de notre scène préfabriqué. Nous allons utiliser la fonction : CraftStudio.Instantiate( [string] nom, [table] scène )


Le nom de notre nouvel objet n’a pas d’importance, appelons le « bullet ». Il faut simplement définir la scène à instancier. Dans le Awake() ajoutez :

self.bulletPrefab = CraftStudio.FindAsset( "prefab_bullet" )

Notre ligne pour créer une nouvelle "bullet" devient :

CraftStudio.Instantiate( "bullet", self.bulletPrefab )

Si vous testez, vous verrez que vos projectiles nouvellement créés apparaissent n’importe où (à l’origine de la scène en réalité) et vont toujours dans la même direction. Il faut donc définir leur orientation et leur origine de départ.

Retournez dans le script « bullet » et ajoutons dans le Awake() :

self.source = CraftStudio.FindGameObject( "Cube" )
 
self.gameObject.transform:SetPosition( self.source.transform:GetPosition() )

self.gameObject.transform:SetOrientation( self.source.transform:GetOrientation() )

Ainsi chaque projectile lors de sa création sera placé au centre de notre objet « Cube » (mon personnage, le votre à peut être un autre nom) et prendra la même orientation.

Il reste un dernier problème : tous ces projectiles créés vont continuer à exister et avancer indéfiniment. A terme cela pourrait nous causer de sérieux problèmes. Nous allons donc leur donner une « durée de vie ».

Dans le Awake() du script bullet, définissez une durée de vie maximum ainsi qu’un compteur permettant de connaitre l’âge de notre objet:

self.MaxLife = 20 
self.life = 0

Puis dans le Update(), ajoutez une ligne pour faire « vieillir » notre projectile à chaque cycle et une condition pour le détruire une fois sont espérance de vie atteinte :

self.life = self.life +1

if self.life > self.MaxLife then
    CraftStudio.Destroy( self.gameObject ) 
end

Et voila !


Script complet :

Script attaché au joueur :

function Behavior:Awake()
   self.vitesse = 0.05
  
   self.groundPlane = Plane:New( Vector3:Up(), -1 )
   self.viseur = CraftStudio.FindGameObject( "viseur" )
   self.cameraComponent = CraftStudio.FindGameObject( "Camera" ):GetComponent( "Camera" )
   self.bulletPrefab = CraftStudio.FindAsset( "prefab_bullet" )
end


function Behavior:Update()
   local horizontal = CraftStudio.Input.GetAxisValue( "Horizontal" )
   local vertical = CraftStudio.Input.GetAxisValue( "Vertical" )
   local mouvement = Vector3:New( horizontal, 0, -vertical )

   mouvement = mouvement * self.vitesse
   self.gameObject.transform:Move (mouvement)

   local mousePos = CraftStudio.Input.GetMousePosition()
   local mouseRay = self.cameraComponent:CreateRay( mousePos )
   local distance = mouseRay:IntersectsPlane( self.groundPlane )
   
   if distance ~= nil then
       local targetPos = mouseRay.position + mouseRay.direction * distance
       self.viseur.transform:SetPosition( targetPos )
       self.gameObject.transform:LookAt( targetPos )
   end
    
   if CraftStudio.Input.IsButtonDown( "Fire" ) then
       CraftStudio.Instantiate("bullet",self.bulletPrefab)
   end
end


Script attaché aux projectiles :

function Behavior:Awake()
   self.speed = 0.5
   self.MaxLife = 20
   self.source = CraftStudio.FindGameObject( "Cube" )
   self.gameObject.transform:SetPosition (self.source.transform:GetPosition())
   self.gameObject.transform:SetOrientation (self.source.transform:GetOrientation())
   self.life = 0
end
 
 
 function Behavior:Update()
     self.life = self.life +1
     self.gameObject.transform:MoveOriented( Vector3:Forward()*self.speed ) 

     if self.life > self.MaxLife then
         CraftStudio.Destroy( self.gameObject ) 
     end
 end

Interférence d'un bloqueur de publicité détectée !


Wikia est un site gratuit qui compte sur les revenus de la publicité. L'expérience des lecteurs utilisant des bloqueurs de publicité est différente

Wikia n'est pas accessible si vous avez fait d'autres modifications. Supprimez les règles personnalisées de votre bloqueur de publicité, et la page se chargera comme prévu.

Sur le réseau FANDOM

Wiki au hasard