Jump to content

Navigating while animating


Spankied
 Share

Recommended Posts

Implementing click navigation. Trying to get skeleton animations & path navigation to work nicely together. I start the player walkAnim  and then begin animating player.position along a path. The walkAnim is promptly interrupted and the player glides along the path, after which he continues walkAnim for a short time. I considered moveWithCollisions, but It navigates to a point, not an array of points, I would have to loop over the path array and check whether or not Ive reached a point, then moveWithCollisions to next point in path. 

Starting to feel out of my league so decided to share my woes with all you. The bablyon-nav-mesh file require()'s alot of dependencies and I was unable to import the library into a playground ( https://www.babylonjs-playground.com/#EZSYWY#1), so I'm just gonna post some code here.

BABYLON.SceneLoader.ImportMesh("","https://rawgit.com/Spankyed/sched-proto/master/src/assets/player/","dummy3.babylon",scene,(meshes,particleSystems,skeletons)=>{

	var skeleton = skeletons[0];
	skeleton.enableBlending(0.2);

	player = meshes[0];
	player.skeleton = skeleton;
	player.position = new BABYLON.Vector3(-2.7426157086231813, 0.32968033243017736, -5.410392414960055);
	player.checkCollisions = true;

	canvas.addEventListener('click', function(event) {
		var pickingInfo = scene.pick(scene.pointerX, scene.pointerY);
		if (!pickingInfo.hit) return;

		var walkRange = skeleton.getAnimationRange("YBot_Walk");
		var walkAnim = scene.beginAnimation(skeleton, walkRange.from, walkRange.to, true);

		var path = navigation.findPath(player.position, pickingInfo.pickedPoint, 'level', navigation.getGroup('level', player.position)) || [];
		console.log('path', path)
		
		/*if path is defined, create path animation frames and beginAnimation on player*/
		if (path && path.length > 0) {
			var length = 0;
			var direction = [{
				frame: 0,
				value: player.position
			}];
			for (var i = 0; i < path.length; i++) {
				length += BABYLON.Vector3.Distance(direction[i].value, path[i]);
				direction.push({
					frame: length*100,
					value: path[i]
				});
			}
			for (var i = 0; i < direction.length; i++) {
				direction[i].frame /= length;
			}
	
			var move = new BABYLON.Animation("CameraMove", "position", 180/length+10, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
			move.setKeys(direction);
			player.animations.push(move);
			scene.beginAnimation(player, 0, 100);			
		}
	})
	engine.runRenderLoop(function(){
		scene.render();
	});
});

While I'm here wanna throw out two other questions I have yet to conceive an answer for. 

How to smoothly adjust the player to lookAt points along its path?

How would key controls(wasd) be implemented in conjunction with a click navigation system?  Create small incremental paths?

 

 

Link to comment
Share on other sites

@Sebavan The tutorial and github repo got me here. Not sure what you mean when you say lookAt will need some epsilon to not look shaky. My question with lookAt is how would you implement it? Would you look at path points, or subdivide between points, and look at subdivisions? And how would u know when to look at a point, would u constantly check if the player has reached certain points?

Link to comment
Share on other sites

About the shakiness, I mean to not reorient every frame if the direction point did almost not move. 

I kind of like the path points idea but I would try both and see which one fits best with your expectation.

You could look at a point until you get close enough to see the one after.

This is all only suggestions and usually heavily depends on the feeling you want to provide in the experience.

Link to comment
Share on other sites

Yo @Spankied ... Here is my 2 cents on how I do things, Babylon Toolkit Style Game Mechanics

First off, Using my style of BJS Game Development... THE COLLIDER IS KING.

The babylon toolkit allow you to create 'Collision Meshes'.  Basically simple primitives to act as the MAIN PLAYER/CHARACTER... For humanoids, I Use a simple Capsule.

The Capsule (Invisible but with things like Check Collision or Physics State on it). This is what you actually move around and interact with. The simple primitive. The character mesh you put inside the capsule as a child is PURE EYE CANDY. You should NEVER (or try not to) directly manipulate the character mesh, he is just along for the ride. If you took the YBot (still in tpose) and no animations, He would just go along the capsule in the TPOSE. Remember the Capsule is the object with all the components and logic on it. NOT THE MESH.

So moving the Capsule around it pretty strait forward, you code use Physics , but MoveWithCollisions would probably be a little LESS resource intensive especially for Non-Player Characters. Once you get the regular capsule moving around like you want (WITH OR WITHOUT the player mesh). Then you use the Toolkit Animation State Machine to setup all your animation logic on the Unity Animation Controller. This way you can have extremely complex or simple animation sequences that are controlled via State Machine Properties.

So you might have a value on your state machine called Forward.... You update the 'Forward' value on your state machine and plays whatever animation (OR BLENDS AND LAYERS OF ANIMATIONS) its supposed to.

BTW... when say LOOK AT... Do you mean have the actual player mesh TURN HIS HEAD, if so you would have to use 'Direct Blend Animation' and turn his head, very much like Blendshapes for Facial Blending. And you need a separate head mesh so you can rotate independently of the body.

OR do you simply mean to rotate the player object (rotate the Y-Axis) to TURN THE WHOLE Capsule Parent Mesh Towards the Path point. I dont think you want to use LookAt unless you always use (0, Point, 0) to rotate or turn your guy that way... The lookAt will rotate the entire object... That may NOT be what you want... Say the next point is on second floor or something if you simply LOOK AT the position you may get UNWANTED rotation in the the whole object... And also if your doing any kind of gradient with rotations... you should SLERP (Spherical Interpolation) not LERP (Linear Interpolation).

I am putting together material to make a Udemy Course that will focus on:

1... Babylon Toolkit Primer - Going over ALL the ins and outs of the Toolkit. How to really get the most out of ALL its features (from custom shaders to complex character animation state machines)

 

2... Babylon Toolkit Game Mechanics - Taking advantage of the Babylon Toolkit Scene Manager to provide that UNITY-LIKE game dev experience and game mechanics.

 

3... Mobile Game Development - Using the various tools to OPTIMIZE your game Mobile.

 

4... Xbox Live Services - Builds-in support for create Native HTML5 UWP (Internally Packaged Or Hosted) console games that have ALL of the features you get with Native C++ Xbox Live Services... Except all built-in the toolkit using TypeScript and newer type TypeScript features like Async/Await for XBOX LIVE API promises.

 

5... Plus we will go thru a PORT a few Unity games. Just to get familiar with using the toolkit to be able to produced the same kind of Games and Mechanics you would use to make a native Unity Game... We just do it Babylon Toolkit Style :)

 

Plus Tons of other stuff that you can now do with the Babylon Toolkit.

 

BUT... I hit a road block in my animation state machine... You cant do any type 2D Blend Trees Yet (2D Simple Directional, 2D Freeform Directional and 2D Freeform Cartesian) I only support 1D and Direct Blending for now... I still dont understand the POLAR SPACE math need to calculate the Input weight of each blend tree child for 2D.

 

But I will keep hacking away at it after I finish some refactoring of the SceneManager API so now can run ALL your Unity-Like Functionality Right win the playground... OR ANY javascript environment like your own custom AngularJS or whatever App you want...

I also create a new Project Referencing Architecture I call project.js (Modeled after Cordova.js plugins)

so you can now reference and use your Unit-Like projects in ANY javascript environment, even the playground.

the entire Babylon Toolkit Project can now be referenced like so:

<script type="text/javascsript" src="project.js"></script>

and

document.addEventListener("projectload", onprojectload, false);

 

even in the playground like so:

 

var createScene = function () {
    // Disable manifest loading
    engine.enableOfflineSupport = false;    

    // This creates a basic Babylon Scene object (non-mesh)
    var scene = BABYLON.SceneManager.CreateScene(engine);

    // Only here to keep playground from giving no camera warning
    var dummy = new BABYLON.FreeCamera("dummy", BABYLON.Vector3.Zero(), scene);

	// Toolkit demo playground root url
	var root = "https://www.babylontoolkit.com/playground/";

    function onprojectload() {
        // Load default playground scene with skybox and hdr reflections
        BABYLON.SceneManager.AppendScene(root + "scenes/", "default.babylon", scene, function() {
            // Get main camera and remove dummy camera
            var camera = scene.manager.getMainCamera();
            if (camera) dummy.dispose();
			
			// Our built-in 'box' shape. Params: name, size, scene
			var box = BABYLON.Mesh.CreateBox("box1", 1, scene);

			// Move the box upward 2 units in height
			box.position.y = 2;
		
			// Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
			var ground = BABYLON.Mesh.CreateGround("ground1", 10, 10, 2, scene);
        });
    }

    // Load project references
    if (!navigator.project) {
		document.addEventListener("projectload", function() { onprojectload(); });
		BABYLON.Tools.LoadScript(root + "project.js");
	} else {
		onprojectload();
	}

	// Console debug reference
	window.scene = scene;
	
    return scene;
};

 

Anyways... The 3.3 Beta Will have all this stuff... Workin on it now :)

 

 

 

 

Link to comment
Share on other sites

@MackeyK24 the issue with the toolkit are the docs. The getting started video link is broken, and I remember just seeing " please refer to unity docs" everywhere. I think there were a few examples, but some felt incomplete or were just api references.  I havent watched a udemy course in like a year, but If u released one on the toolkit I would definately get it. Any video u release on the toolkit I'll watch, especially those in regards to navigation and animation. 

Idk why collision meshes or impostors never crossed my mind. Makes so much sense after reading ur post.

I want to incorporate both lookAt functionalities u mentioned, but for now, just the second one, turning the capsule to face the movement direction. Is there another function other than lookAt u would use? If i moveWithCollisions to a point I can just look at that point before moving, but how would I do this for a player.position animation over an array of points?

To elaborate on last question, moveWithCollisions only moves to one point, that's why I began an animation on the player.position value and made some frames for each point along the path, then play all frames. How would a moveWithCollisions refactor look?

Does project.js also import the navigation-mesh library? If so how are u able to load it in the playground, I checked the navmesh library file and it tries to require a bunch of dependencies which the playground didn't like.

Thanks for ur response Mackey

Link to comment
Share on other sites

First the video, well I haven’t made yet. I’m still cleaning up a few things to make projects easy to use anywhere, like the playground. I am also trying to find something good to make as a getting started project. Like the roller bal or some kind of basket shooter. Something good but not to complicated as your first toolkit project.

The many refer to unity links. I made the toolkit work off the native unity workflows and properties... They get serialized as metadata. So you use a toolkit editor feature EXACTLY like you would if making a native unity game, except for Components. We don’t support unity components but we have a growing set of Babylon components for our projects. So for example, animation controllers. You would setup an animation controller in unity editor, nothing different you do for a Babylon project as far as the setup. You have to be familiar with unity mechanim to really get most out it. Whatever you setup, the toolkit parse out and that metadata to re-implement that functionality in the BabylonJS client side code. So everywhere it says refer to unity docs for that feature, well you gotta go look how unity does it. Once you get unity doing it and you export the toolkit takes over serializing detailed export content. 

Anyways, my point being, you gotta get to know the unity editor a bit. For the toolkit, that’s you life blood, your main game development environment.

I do EVERYTHING in the toolkit (or via a toolkit VSCode project. I even use the toolkit to make the toolkit. Talk about the chicken and the egg ?

The toolkit in one screen and a VSCode toolkit project in another screen are my main game development workflow tools

Link to comment
Share on other sites

The navmesh. Yes project.js will bring in all required libs NOT already loaded, including navmesh. 

Unfortunatly the navmesh is acting funny on the playground so I can’t show you any examples on the playground yet. @Deltakosh and I are working on it. Hopefully we can get that issue fixed soon.

So for now, you gotta use a full toolkit project to play with navigation

Link to comment
Share on other sites

moveWithCollisions takes a velocity. The nav-mesh library outputs an array of positions. My question is how do I move a player using this array of positions. Using begin animation, I can set which position player should be at, at certain frames. This works well except I can't animate position and skeleton at same time. Halppp!1

Link to comment
Share on other sites

1 hour ago, Spankied said:

moveWithCollisions takes a velocity. The nav-mesh library outputs an array of positions. My question is how do I move a player using this array of positions. Using begin animation, I can set which position player should be at, at certain frames. This works well except I can't animate position and skeleton at same time. Halppp!1

Using the pattern COLLIDER IS KING ... The mesh containing the skeleton has NOTHING to do with the actual position of the PARENT COLLIDER that you should moving between nav points.

Make a BoxMesh. Set:

collisionMesh.checkCollision = true;

collisionMesh.visibility = 0.0;

dude.parent = collisionMesh;

/// MOVE THE COLLISION MESH BETWEEN WAYS POINTS

Normalize the position to get direction vector.

collisionMesh.moveWithCollision(directionVector.scale(movementSpeed))

 

Now for the CHILD DUDE MESH... HE NEVER MOVES HIS POSITION... HE JUST ALONG FOR THE RIDE...

 

While riding he can play (IN-PLACE) animations...

 

Now I dont really use beginAnimation to play skeletal animations... I need full control over bones, layers, blending etc... So I use my BABYLON.AnimationState component to set the state of what I want my guy to do...

 

So while moving in between animations... If always MOVING.... Before I start the guy on the waypoints... I would do something like in a Scene Component:

 

let animator = this.getComponent("BABYLON.AnimationState");
if (animator) animator.play("Walk");

 

But you could always us beginAnimation for simple skeleton animation.

scene.beginAnimation(...) on your dude skeleton and he just play his walk  animation while the parent collision mesh is actually moving around... One has nothing to do with the other (as far as not being able to move the parent with an animation and play a walk animation on the child dude mesh at the same time)

 

 

 

 

 

 

Link to comment
Share on other sites

@Spankied, It used to be called velocity but it was always displacement. Eventually the document was updated to avoid the confusion. see

http://doc.babylonjs.com/api/classes/babylon.mesh#movewithcollisions

You are supposed to give the amount and direction by which you want to displace the mesh.

If you search the forum you might find a discussion on that

Link to comment
Share on other sites

Yo @Spankied ... I dont think you need to use LookAt... Again that does rotation on all Axis... I think you you can just rotate (turn) with the rotation alpha from direction.

 

Try something like this:

let navpoint:BABYLON.Vector3 = GetCurrentNavPointFromPaths();
            
let navposition:BABYLON.Vector3 = navpoint.subtract(collisionMesh.position);
            
let navdirection:BABYLON.Vector3 = navposition.normalize();
            
let navrotation:number = Math.atan2(navdirection.x, navdirection.z);
            
collisionMesh.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(navrotation, 0, 0);
            
collisionMesh.moveWithCollisions(navdirection.scale(movementSpeed));

You can optimize of course using the "ToRef" versions of the API functions.

UPDATE

I tested this with nav points in front, behind and above the collisionMesh... Keeps the collisionMesh from Pitching and Rolling... 

And it does rotate toward then moves with collisions to the nav point.

Seems to work for me :)

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...