In this example I'm going to show you how I used terrain alpha maps to check for certain textures when the player is walking on them. I used the first person character controller but you can use this with any type of player or object as it only needs a transform position to work. I have a game that generates a maze at the start of the game. The player is dropped into the maze from a height of about 10 feet or so. The problem is that if I click the player object and change the inspector from normal to debug, I see that the character is still continuously generating falling velocity. I have a sphere at the bottom of the character that is supposed to do a ground check but clearly that isn't working.
This is the relevant code for one of the ground tiles and the ground check features of the character. In Unity Terrain textures are stored as Alpha Maps or "Splat Maps", which are arrays of values that hold the mix of each different texture at every point on the Terrain. It's possible to detect what mix of textures the player is standing on at any given moment by converting the player's current transform position to a coordinate on the alpha map image. This can then be used to check the Alpha Map data at that position.
This is ideal for determining what footstep sound should play. In this post I'll show you how to detect what surface material the player is standing on step by step and how you can use that data to trigger footstep sounds. I am unsure how to avoid this behavior, so I will be using the Physics.CheckCapsule approach ins$$anonymous$$d. ProcessActions() simply reads in inputs and applies movement and turning.
We clamp the inputs of turn and move between -1 and 1 to prevent unintended super-speed. Moving is done by actually changing the position of the character . There is no force applied, so friction is ignored and the character technically has no velocity. Collisions still work perfectly in the tests I've done.
Jumping requires a check to make sure we allow jumping and that the character is grounded, but then applies an upward velocity to the character via rigidbody.AddForce(). If possible, use primitive colliders on gameObjects, like sphere, box, or cylinder, and not mesh colliders. You can compose your final collider from more than one of these colliders. Physics can be a performance bottleneck of your application because of its CPU overhead and collisions between primitive colliders are much faster to calculate. You can also adjust Fixed Timestep setting in Time manager to reduce the frequency of physics fixed updates when the accuracy of physics interaction isn't so necessary. In Unity, you can achieve draw calls reduction by using static batching for still objects and dynamic batching for the moving ones.
However, you have to prepare your scenes and models first , and batching of dynamic objects works only for low-res models. In general, the key is to use as little materials as possible and share them across the scene. You will sometimes need to create atlases from textures to be able to share one material between distinct objects.
A good tip is also to use higher resolution of scene lightmaps textures to lower their number when you are baking light in larger environments. When checking for ground to snap to it makes sense that we only consider geometry that could represent ground. By default the raycast checks anything except for objects put on the Ignore Raycast layer. What shouldn't count can vary, but the spheres that we're moving most likely don't. We won't accidentally hit the sphere we're casting for, because we're casting from its position outward, but we might hit another moving sphere. To avoid that we can set their Layer to Ignore Raycast, but let's create a new layer for everything that's active and should be ignored for this purpose.
The CharacterController already has a variable to know if the character is grounded but I found it buggy and I tend to determine myself if the player is grounded. I Like to use the CheckSphere method from the Physics Class. It returns true if any colliders intersect the sphere defined by the parameters. I like to use an empty gameObject child of my player as center of the sphere and then I use a variable for the radius and the layer. This way I can control in editor the way I define the grounded status of my character.
Most of the time, the simplest way to create character movement in Unity, including making a player jump, is to do it with physics, by adding a Rigidbody component to the object and applying forces to it. Once you´ve set up collisions, your solver will begin generating collision constraints for particles, using the 3 steps outlined above. Obi uses a collision detection paradigm known as "speculative contacts". This means contacts will be generated before any actual collision has taken place between particles, or between colliders and particles. Contacts are detected and resolved even at high speeds. Also, TOI ordering is not needed if several collisions happen in the same frame.
Layer collision matrix.Now enable the stairs mesh collider components again. Then add a few small rigidbody objects to fall on top of them to see both kind of interactions at the same time. If you give those objects a low enough mass—like 0.05—the spheres will be able to push them aside. It's important to note that the value used (1.0f in this case) is going to vary based on your setup, so you'll want to tweak and debug to determine what value works for your game. Integrating this character controller with ML-Agents is really simple.
You just need to create a Heuristic() function in your Agent class that reads inputs from the player and an OnActionReceived() function that converts actions to inputs and feeds them into the character controller. This code assumes your agent is set up to use DiscreteActions, but ContinuousActions should be even easier, since you just need to feed the values directly in . To move the character according to the player's inputs, we use the MovePosition function.
This function tries to move the player to a given position while respecting the collisions rules. This way, the player's movement are "separated" from the other physic interaction. Sometimes, when moving objects in the scene, we don't realize that the object has a collider on it and that changing its position will force the engine to recalculate the whole physical world all over again. In that case, you should add Rigidbody component to it (you can set it to non-kinematic if you don't want external forces to be involved). A good starting point is the Unity component system itself. Complications may appear when particular components need to communicate with other systems of the application.
For this, you can use interfaces to make parts of your system more abstract and reusable. Alternatively, you can use an event-driven approach for reacting to particular events from outside scope, either by creating a messaging system or by registering directly to parts of the other system as listeners. It should be exclusively its controller's responsibility.
The Character Controller component provides a straightforward way to add movement, and jumping, to your game quickly and easily. It works particularly well for first person games and allows you to create collision-based movement without needing to use physics. While you will need to manually check for the floor and other static objects when creating your own jumping movement in 2D, in 3D, Unity provides a built-in Component that makes collision detection a little easier. With the latest developments for the graphics technology and the engine capabilities in the Unity engine, many of the obstacles that existed previously for realistic digital humans creation are falling away.
This limits what stories they are able to tell and how well the players can interact with these characters. With the current complex, clunky, fragile, bespoke pipeline with tens of custom steps and varied tools that all need to be hooked up together, a single high-quality character can cost upwards of 4 months for a team of 12 to create! Simply put, character creation is one of the costliest aspects of game creation. And if this is a challenge for large studios, it's an incredible burden for small indie creators. For continuous collision detection you would need to CapsuleCast from your origin point to the point you moved to in order to retrieve any colliders the controller "skipped" if it's moving extremely fast. This is overall pretty easy to implement so it's really something I should do.
This is fine, but problems appear once the character is standing on a slope. If we now fire a raycast directly downwards the point we contact is no longer the closest point to our "feet." This will cause issues with our ground clamping method . Add a ObiCollider component to any collider in your scene to make it work with Obi. You can add this component to SphereColliders, MeshColliders, BoxColliders... Pretty much all standard Unity colliders, both 3D and 2D.
The only collider type not currently supported by Obi is PolygonCollider2D. At the beginning of each simulation step, solvers will generate collision constraints for all their particles based on what colliders are spatially close to them. Unlike a Character Controller, it's not good practice to set the position or rotation of a rigidbody, or scale a rigidbody object constantly . Instead, you should use theAddForce()andAddTorque()methods found in theRigidbodyclass. It is okay to directly set the position and rotation of a Rigidbody if, for example, you're spawning in the object for the first time, or resetting the scene.
In that situation it will be fine, as long as the Rigidbody is not intersecting other objects. Next, I need to work out where on the alpha map I'm going to check for textures by converting the world position of the player to a coordinate on the alpha map. To do this, I'm going to create a new function called ConvertPosition that takes one parameter, a Vector3, which I'll use to hold the player's position. Well, when we're using the character controller we have a lot of freedom but at the same time we have to code a lot of stuff ourselves even for simple actions like jumping or gravity. Don't use performance intensive things in update loops, use caching instead.
A typical example is an access to components or other objects in a scene or intensive calculations in your scripts. If possible, cache everything in Awake() methods, or change your architecture to a more event-driven approach to trigger things just when they're needed. Prototyping and implementation of functionality in Unity is quite easy.
You can easily drag and drop any references to other objects, address every single object in the scene, and access every component it has. On top of noticeable performance issues , there is also great danger in making parts of your code entirely dependent on each other. Or being dependent on other systems and scripts unique to your application, or even on the current scene, or current scenario.
Try to take a more modular approach and create reusable parts which can be used in other parts of your application, or even shared across your whole application portfolio. Build your framework and libraries on top of Unity API the same way you are building your knowledge base. While this method of creating a jump force based on a target height is very consistent (i.e. the height that the player can jump will be the same every time) it's not 100% accurate. Compound Colliders are combinations of primitive Colliders, collectively acting as a single Rigidbody.
They come in handy when you have a model that would be too complex or costly in terms of performance to simulate exactly, and want to simulate the collision of the shape in an optimal way using simple approximations. To create a Compound Collider, create child objects of your colliding object, then add a Collider component to each child object. This allows you to position, rotate, and scale each Collider easily and independently of one another. You can build your compound collider out of a number of primitive colliders and/or convex mesh colliders.
The representative of the Russian Federation recalled that, on 24 March 1999, the United States and its North Atlantic Treaty Organization allies began their military aggression against the Republic of Yugoslavia. They carried out more than 35,000 bombing runs and more than 2,000 Serbs died as a result — including women, children and older people — he said, adding that thousands of civilian objects and infrastructure were destroyed. That would later be "cynically called collateral damage", he said, spotlighting that conflict as a tragic contribution to European history by "so-called defensive forces". The resolution's ultra vires adoption is destructive, null and void, and creates no legal consequences, he stressed, voicing hope that Western States will remember "this lesson in the manipulation of humanitarian principles". If you make a button object from the menu in unity, it creates a game object with a Sprite and Button component . Similarly, the main camera typically has several components in addition to the Camera component attached.
Another bad side effect that can occur when, say, moving a rigidbody along an axis for player movement is that internally the rigidbody is simulated and then it applies it's position. Updating the position then moves the rigidbody without taking into account the velocity change and such. If the rigidbody is rolling back down a slope, it will be moving the rigidbody backwards while your position altering code is moving the rigidbody back up the slope.
Treating stairs as ramps, max ground angle 46°.While it requires some additional level design work, using simplified colliders for stairs is the best way to make them navigable using physics. In general it is a good idea to make collision shapes as simple as possible, avoiding needless details both for performance and movement stability reasons. But it is an approximation, so on close inspection you'll see that the spheres both cut through and hover above the stair steps.
However this usually isn't that obvious from a distance and while in motion. Simplified stairs, as normal objects and as colliders.Disable the mesh collider components of the stairs, but don't remove them at this point. Then temporarily increase the max ground angle to 46° so the spheres can move up the 45° stairs.
We only want to snap when there's ground below the sphere to stick to. We can check this by casting a ray from the sphere body's position straight down, by invoking Physics.Raycast with body.position and the down vector as arguments. The physics engine will perform this raycast and return whether it hit something. Three physics steps; timestep 0.2; time scale 0.5.The physics step during which the sphere gets launched still has a collision. We act on that data during the next step, so we think that we're still grounded while we no longer are. It's the step after that when we no longer get collision data.
So we're always going to be a bit too late, but this isn't a problem as long as we're aware of it. You can do the logic either on the Holder or on the Groundcheck, I'm assuming you put it on the Holder. Generally, you make a game object variable, check "inspector" to see it nicely on the FSM "front page" and then drag your Groundcheck game object into it . To learn a few good practices, let's add a Game Object is Null action first into Start.
If the variable wasn't set, we want to ring the alarm. On the new state, right click and hit "Toggle Breakpoint". So, we'll use the bIsGoingRight boolean to get the direction our ennemy is going, multiply it by the time elapsed and the monster's movement speed. The result will be used as an input of the transform.Translate method to move our gameobject according to its movement speed and current direction. CheckGrounded() will check whether the character is on the ground and update the IsGrounded variable. We need to make sure the character is on the ground or else holding the jump input button will make the character fly into the sky!
This will also take the slope into consideration so that the character can't jump if sliding down a too-steep slope. Second is FixedUpdate(), which gets called every .02 seconds by Unity alongside physics updates. Often, code uses Update(), but that is called every frame, which won't work well for character updates that are affected by physics because framerate can vary significantly based on your computer and how complex your scene is. The two functions don't exist yet, so we'll create them below. Sometimes it's not possible to have this correctly set from your 3D modeling software because of different units these applications are using. To make everything right, set the scale factor in models import settings (leave 0.01 for 3dsMax and Modo, set 1.0 for Maya), and note that sometimes you will need to re-import objects after changing the scale setting.



























