I. Introduction▲
Cette série explique pas à pas la création d'un contrôleur pour le mouvement d'un personnage dans un jeu de plateformes 2D.
Vous pouvez retrouver les autres épisodes de cette série dans le sommaire dédié.
II. Vidéo▲
Unity - Contrôleur pour personnage d'un jeu de plateformes - Mouvement horizontal
III. Résumé▲
Dans cette vidéo, nous allons implémenter le mouvement horizontal.
III-A. Implémentation▲
Pour implémenter le mouvement horizontal, nous allons réutiliser la fonction Movement(). Le mouvement horizontal est géré en premier afin d'avoir un meilleur résultat avec les rampes :
using
System.
Collections;
using
System.
Collections.
Generic;
using
UnityEngine;
public
class
PhysicsObject :
MonoBehaviour {
public
float
minGroundNormalY =
.
65f
;
public
float
gravityModifier =
1f
;
protected
Vector2 targetVelocity;
protected
bool
grounded;
protected
Vector2 groundNormal;
protected
Rigidbody2D rb2d;
protected
Vector2 velocity;
protected
ContactFilter2D contactFilter;
protected
RaycastHit2D[]
hitBuffer =
new
RaycastHit2D[
16
];
protected
List<
RaycastHit2D>
hitBufferList =
new
List<
RaycastHit2D>
(
16
);
protected
const
float
minMoveDistance =
0
.
001f
;
protected
const
float
shellRadius =
0
.
01f
;
void
OnEnable
(
)
{
rb2d =
GetComponent<
Rigidbody2D>
(
);
}
void
Start (
)
{
contactFilter.
useTriggers =
false
;
contactFilter.
SetLayerMask (
Physics2D.
GetLayerCollisionMask (
gameObject.
layer));
contactFilter.
useLayerMask =
true
;
}
void
Update (
)
{
targetVelocity =
Vector2.
zero;
ComputeVelocity (
);
}
protected
virtual
void
ComputeVelocity
(
)
{
}
void
FixedUpdate
(
)
{
velocity +=
gravityModifier *
Physics2D.
gravity *
Time.
deltaTime;
velocity.
x =
targetVelocity.
x;
grounded =
false
;
Vector2 deltaPosition =
velocity *
Time.
deltaTime;
Vector2 moveAlongGround =
new
Vector2 (
groundNormal.
y,
-
groundNormal.
x);
Vector2 move =
moveAlongGround *
deltaPosition.
x;
Movement (
move,
false
);
move =
Vector2.
up *
deltaPosition.
y;
Movement (
move,
true
);
}
void
Movement
(
Vector2 move,
bool
yMovement)
{
float
distance =
move.
magnitude;
if
(
distance >
minMoveDistance)
{
int
count =
rb2d.
Cast (
move,
contactFilter,
hitBuffer,
distance +
shellRadius);
hitBufferList.
Clear (
);
for
(
int
i =
0
;
i <
count;
i++
) {
hitBufferList.
Add (
hitBuffer [
i]
);
}
for
(
int
i =
0
;
i <
hitBufferList.
Count;
i++
)
{
Vector2 currentNormal =
hitBufferList [
i].
normal;
if
(
currentNormal.
y >
minGroundNormalY)
{
grounded =
true
;
if
(
yMovement)
{
groundNormal =
currentNormal;
currentNormal.
x =
0
;
}
}
float
projection =
Vector2.
Dot (
velocity,
currentNormal);
if
(
projection <
0
)
{
velocity =
velocity -
projection *
currentNormal;
}
float
modifiedDistance =
hitBufferList [
i].
distance -
shellRadius;
distance =
modifiedDistance <
distance ?
modifiedDistance :
distance;
}
}
rb2d.
position =
rb2d.
position +
move.
normalized *
distance;
}
}
III-B. Test▲
Pour tester votre implémentation, vous pouvez créer un nouveau script, héritant du premier et dans lequel vous faites en sorte que la variable targetVelocity soit définie de manière appropriée pour simuler un mouvement vers la droite.
N'oubliez pas de désactiver le composant PhysicsObject() afin de ne pas appliquer deux fois la gravité sur l'objet.
IV. Ressources▲
Vous pouvez télécharger les ressources pour ce projet ici.
V. Commenter▲
Vous pouvez commenter et donner vos avis dans la discussion associée sur le forum.