Ok, thanks for the reply, I will see to upgrade to the new version here!
Thank you.
Hi, Iāve been sniffing around for a while and tried to some moderate success to mount the player to another character. What is the best approach to this?
Say I have a horse, creature, vehicle, boat.
What is the best way to freeze the player movement, parent it to another character and give control to the other character?
What Iāve done now is to disable the rigidbody, and all the movement scripts on the player, then enable the input on the other object Iām controlling. Afterwards when dismounting I reenable scripts and rigidbody and turn off the input on the other character. Is there a better ECM2 way?
I really like the new hook-based architecture with the newest release, and I was wondering what your suggestion would be for implementing sort of ācompositeā actions which require multiple button presses. For example, I want my character to not only have a default jump as implemented within the default Character class, but also have the ability to do a high jump if they initiate a jump while crouching, and a long jump if they initiate a jump while crouching and moving (think any sort of classic 3d platformer movement).
Iām sure there are multiple ways to accomplish the same thing, but Iām just curious if thereās a āmore correctā option with the way the new architecture is laid out.
Hello,
You can use the Character Pause method, which disables both the Characterās collisions and Capsule Collisions.
Although ECM2 is a fully kinematic character controller and CharacterMovement is responsible for managing collision detection and response, the Capsule Collider is still recognized by Unityās Physics engine. This means that other dynamic rigidbodies will interact with the Characterās capsule, even if the Character script is disabled.
To solve this, use the Character Pasue method, as this disables both, Character collisions (algorithm) and its Capsule Collider (Unity Physics)
Hi, Iām glad you like the new version!
Regarding your question:
I agree there are many ways to handle this. One option, favoring composition, is to create a separate āAbilityā script for jumping. This script can manage all jumping-related logic, including replacing the built-in jump functionality and adding any extra mechanics you need.
This approach consolidates all the jumping mechanics into a single script, making it easier to manage and modify.
Another approach is to reuse the built-in jump mechanic by extending the Character class and overriding or augmenting its jump-related methods. This way, you can incorporate additional conditions and trigger specific jumps as needed.
Hi @Goodgulf ,
Thatās pretty cool and will definitely help others. Thank you very much for sharing it with us!
Hey,
Is there a way to reduce speed depending on character movement direction? Iād like backwards movement to be 50% slower and sideways movement (strafing) to be 25% slower.
Hi @desukarhu ,
For this, I suggest creating a custom character class (extending the Character class) and overriding its GetMaxSpeed method. This will allow us to apply a modifier to the actual character speed (e.g., walking, falling, crouching, etc.). In our case, it will be a directional movement modifier. For example:
public float forwardSpeedMultiplier = 1.0f
public float strafeSpeedMultiplier = 0.75f;
public float backwardSpeedMultiplier = 0.5f;
protected float CalculateDirectionalModifier()
{
// Compute planar move direction
Vector3 characterUp = GetUpVector();
Vector3 planarMoveDirection = Vector3.ProjectOnPlane(GetMovementDirection(), characterUp);
// Compute actual walk speed factoring movement direction
Vector3 characterForward = Vector3.ProjectOnPlane(GetForwardVector(), characterUp).normalized;
// Compute final directional modifier
float forwardMovement = Vector3.Dot(planarMoveDirection, characterForward);
float speedMultiplier = forwardMovement >= 0.0f
? Mathf.Lerp(strafeSpeedMultiplier, forwardSpeedMultiplier, forwardMovement)
: Mathf.Lerp(strafeSpeedMultiplier, backwardSpeedMultiplier, -forwardMovement);
return speedMultiplier;
}
public override float GetMaxSpeed()
{
float actualMaxSpeed = base.GetMaxSpeed();
return actualMaxSpeed * CalculateDirectionalModifier();
}
The CalculateDirectionalModifier function uses the dot product to determine how much the character is moving along its forward vector. It later uses this value (ranging from -1 to 1) to compute the final movement modifier. Finally, this speed modifier is applied in the Characterās GetMaxSpeed method, returning the final modified speed.
Would be great if the Demo scene could work without needing to import Cinemachine into the project. We only want to use the first-person controller in our game. The Demo scene has a lot of useful examples to play with, but I cannot load in unless I get Cinemachine and then switch perspectives. (Iām on Unity 6 btw)
Hi @fendercodes
Thanks for the suggestion! Iāll include it in the next update.
Thanks! Separately, I am looking to use Fusion v2 and I imported your example for it. If weāre going to be using fusionās Shared Mode for our project, what parts of your example scripts should we port to our own player controller? I am aware that in Shared mode some of the things arenāt possible / going to work that might in Client Host mode / dedicated server mode.
Hi @fendercodes
The included Fusion 2 example is designed for a fully server-authoritative mode. In your case, there isnāt much to transfer from this example to a shared mode, and itās actually unnecessary. Shared mode is more similar to single-player games than to server-authoritative mode with client-side prediction, making it more straightforward.
To implement shared mode, you basically need to check for authority before moving the character (i.e., before calling SetMovementDirection, Jump, StopJumping, etc.), as demonstrated in the Fusion Shared Mode Basics tutorial. Additionally, ensure that you disable the characterās auto-simulation and interpolation for non-locally controlled characters, as Fusionās NetworkTransform will manage this for remote players.
Hi @Krull
Iām trying to get Characters to collide with each other, for organization sake and also for handling collision I have a Default layer (ground, walls and everything world related) and Pushbox (Physics collider used by characters or other pushables in the game), my understanding is that I had to put on the CharacterMovement.CollisionLayers both layers for the characters to start colliding with each other but now they also consider themselves as valid ground, I have tried using the SlopeLimitBehavior on their Pushbox collider to try and override it as NotWalkable but it doesnāt seem to make any difference, am I doing something wrong here or is this not possible?
Hi, @BigGreenPillow ,
Thatās correct, the CollisionLayers define all the layers a character should consider during its movement, including the grounding phase.
To solve this, you can make use of the CharacterMovement.ColliderFilterCallback. This allows us to fine-tune collisions based on our own criteria. In your case, you can filter based on specific layers.
Hi Krull,
ā[Obi] solvers now update the simulation in LateUpdate(), but using a fixed timestep. Unless youāre also updating the position of the target transform in LateUpdate() and thereās no explicit script execution order set, there should be no lag.ā
Using Obi Rope Iām having trouble with it syncing to the players hand transform and it sort of lags behind. Is this likely because of the LateFixedUpdate simulate? How should I work around this?
I canāt figure this outā¦ My character slides on the ground after landing from a launch?.. Iāve tried turning off everything else, but it still happens.
Hi @Asarge,
You can configure the script execution order to ensure that a character is updated either before or after Obi, depending on your needs.
Alternatively, you can disable automatic character simulation by setting enableAutoSimulation
to false
, and then manually trigger simulation by calling the Simulate
method.
Either approach should work, I believe
Hi @AustinDrozin,
Could you share your character settings so I can get a better understanding of what could be the cause.
Also is the box a trigger or a collider? as if is a collider this could be the reason of the strange behaviour.