In the previous few blog total, we have been systematically learning the auto-pathfinding plugin Navmesh related concepts and details. However, if you want to do a beautiful hand tour of the scene, you need to use a variety of complex scene terrain, and not just on the ground of automatic pathfinding. Today we will run through the details with a complete and complex example. We will implement a complex scene in which characters can climb, jump, and climb. It feels like the CS game of the year. This case will use some basic animation functions, you can first combine the document has a general understanding. This example is processed on the official paradigm.
(Reprint please specify original address http://blog.csdn.net/janeky/article/details/17598113) step 1. Place various models in the scene, including floor, ramp, mountain, escalator, etc.
2. Add navigation static and Offmeshlink generatic for all models (this requires, for example, that the floor is connected to the ramp and the ramp does not need to be added offmeshlink)
3. Special handling escalator, need to manually add off Mesh Link, set the start point and end point
4. Save the scene, bake the scene
5. Add the role model to the NAV Mesh agent component
6. Add a new script for the character, AgentLocomotion.cs, to handle the auto pathfinding, already the character animation transformation. Code is long, you can combine annotations to understand
Using Unityengine;
Using System.Collections;
public class Agentlocomotion:monobehaviour {private Vector3 target;//target location private navmeshagent agent;
Private Animation anim;//Animation private String locostate = "Locomotion_stand"; Private Vector3 linkstart;//offmeshlink start point private Vector3 Linkend;//offmeshlink end point private quaternion linkrotat E;//offmeshlink Rotation private bool begin;//whether to start pathfinding//use of this for initialization void start () {Agen
t = getcomponent<navmeshagent> ();
Automatically move and close the offmeshlinks, i.e. the offmeshlink,agent generated directly from the two isolated obstructions will not automatically cross Agent.autotraverseoffmeshlink = false;
Create animation Animationsetup ();
Starting a co-process, processing animation state machine Startcoroutine (Animationstatemachine ());
} void Update () {//left mouse button click if (Input.getmousebuttondown (0)) {//Camera-to-click-position Ray
Ray Ray = Camera.main.ScreenPointToRay (input.mouseposition);
Raycasthit hit; If (Physics.raycast (Ray, out hit))
{//Determine if the click is terrain if (hit.collider.tag.Equals ("obstacle")) {
begin = True;
Click position coordinates target = Hit.point; }}}//Each frame, set the target point if (begin) {Agent.
Setdestination (target); }} IEnumerator Animationstatemachine () {//based on locostate different state to process, call related function while (application.is
Playing) {yield return startcoroutine (locostate);
}}//Stand IEnumerator Locomotion_stand () {do {updateanimationblend ();
Yield return new Waitforseconds (0);
} while (agent.remainingdistance = = 0);
Not reaching the target point, go to the next state locomotion_move locostate = "Locomotion_move";
yield return null; } IEnumerator Locomotion_move () {do {UpdateANimationblend ();
Yield return new Waitforseconds (0); The character is in Offmeshlink, depending on the location, choose a different animation if (agent.isonoffmeshlink) {locostate = Selectli
Nkanimation ();
return (true);
}} while (Agent.remainingdistance! = 0);
has reached the target point, the state to stand locostate = "Locomotion_stand";
yield return null;
} IEnumerator Locomotion_jump () {//Play jump animation string linkanim = "Runjump";
Vector3 Posstart = transform.position; Agent.
Stop (TRUE); Anim.
Crossfade (Linkanim, 0.1f, Playmode.stopall);
Transform.rotation = linkrotate;
Do {//calculates a new position for float tlerp = anim[linkanim].normalizedtime;
Vector3 Newpos = Vector3.lerp (Posstart, LinkEnd, TLERP);
Newpos.y + = 0.4f * Mathf.sin (3.14159f * tlerp);
Transform.position = Newpos;
Yield return new Waitforseconds (0); } while (Anim[linkanim].normalizedtime < 1); The animation reverts to the idle anim.
Play ("Idle");
Agent.completeoffmeshlink (); Agent.
Resume ();
The next state is stand transform.position = linkend;
Locostate = "Locomotion_stand";
yield return null; }//Ladder IEnumerator Locomotion_ladder () {//Ladder center position Vector3 Linkcenter = (Linkstart + linkend)
* 0.5F;
String Linkanim;
Judge whether it is on a ladder or under a ladder if (Transform.position.y > linkcenter.y) linkanim = "Ladder down";
else Linkanim = "Ladder up"; Agent.
Stop (TRUE);
quaternion Startrot = transform.rotation;
Vector3 startpos = transform.position;
float blendtime = 0.2f;
float tblend = 0f; Positional interpolation change of the character (within 0.2 changes) do {transform.position = Vector3.lerp (Startpos, Linkstart, Tblend/blend
Time); Transform.rotation = Quaternion.lerp (Startrot, Linkrotate,Tblend/blendtime);
Yield return new Waitforseconds (0);
Tblend + = Time.deltatime;
} while (Tblend < blendtime);
Set position transform.position = Linkstart; Plays the animated Anim.
Crossfade (Linkanim, 0.1f, Playmode.stopall); Agent.
Activatecurrentoffmeshlink (FALSE);
Wait for the animation to end do {yield return new waitforseconds (0);
} while (Anim[linkanim].normalizedtime < 1); Agent.
Activatecurrentoffmeshlink (TRUE); Restores the idle state anim.
Play ("Idle");
Transform.position = LinkEnd;
Agent.completeoffmeshlink (); Agent.
Resume ();
Next state stand locostate = "Locomotion_stand";
yield return null; } private String Selectlinkanimation () {//Get current Offmeshlink data offmeshlinkdata link = Agent.curren
Toffmeshlinkdata; Calculates whether the role is currently at the start or end point of the link (because Offmeshlink is bidirectional) float DistS = (transform.position-link.startpos). Magnitude;
float Diste = (transform.position-link.endpos). magnitude;
if (DistS < diste) {Linkstart = Link.startpos;
LinkEnd = Link.endpos;
} else {linkstart = Link.endpos;
LinkEnd = Link.startpos;
} The direction of//offmeshlink Vector3 aligndir = Linkend-linkstart;
Ignore y-Axis aligndir.y = 0;
Calculate rotation Angle Linkrotate = quaternion.lookrotation (Aligndir); Determine if the Offmeshlink is manual (stair) or automatically generated (jumping) if (Link.linktype = = offmeshlinktype.linktypemanual) {Retu
RN ("Locomotion_ladder");
} else {return ("Locomotion_jump");
}} private void Animationsetup () {anim = getcomponent<animation> ();
Put the walk and run animations on the same layer and synchronize their speed.
anim["Walk"].layer = 1;
anim["Run"].layer = 1; Anim.
Synclayer (1); Set "Jump", "Climb Stairs", "Down stairs" animation mode and speedDegree anim["runjump"].wrapmode = Wrapmode.clampforever;
anim["Runjump"].speed = 2;
anim["Ladder up"].wrapmode = Wrapmode.clampforever;
anim["Ladder up"].speed = 2;
anim["Ladder down"].wrapmode = wrapmode.clampforever;
anim["Ladder down"].speed = 2; The initialization animation state is idle anim.
Crossfade ("Idle", 0.1f, Playmode.stopall);
}//Update animation fusion private void Updateanimationblend () {//walk speed float walkanimationspeed = 1.5f;
Run speed float runanimationspeed = 4.0f;
Speed threshold (idle and walk critical point) float speedthreshold = 0.1f;
Speed, only consider x and z Vector3 velocityxz = new Vector3 (agent.velocity.x, 0.0f, agent.velocity.z);
Velocity value float speed = velocityxz.magnitude;
Set the speed of the run animation anim["Run"].speed = Speed/runanimationspeed;
Sets the speed of the Walk animation anim["Walk"].speed = speed/walkanimationspeed; Depending on the speed of the agent, determine the playback status of the animation if (Pace > (wAlkanimationspeed + runanimationspeed)/2) {Anim.
Crossfade ("Run"); } else if (Speed > Speedthreshold) {anim.
Crossfade ("Walk"); } else {Anim.
Crossfade ("Idle", 0.1f, Playmode.stopall); }
}
}
The effect diagram is as follows, click any place, the character can automatically find the way past. There may be different obstacles in the middle, we can see the character as we expected, can jump down, can climb stairs, and finally reach the target point.
Summary
Today's example is more complex, depending on the type of grid, to deal with the role of the action is ordinary pathfinding, or climbing, or jumping. This example should be relatively close to the real project. Everyone in the actual project if there is more complicated to find the road, welcome to explore. Ken@iamcoding.com
Source Code
Http://pan.baidu.com/s/1i35cVOD
References 1.http://www.xuanyusong.com/
2.http://liweizhaolili.blog.163.com/
3.http://game.ceeger.com/components/class-navmeshagent.html