I have a character with a NavMeshAgent
I have a Movement MonoBehaviour attached to that same object.
Say I want to initialize the movement speed. Should I do it in the NavMeshAgent in inspector or make a serialized field in the Movement script that assigns it to the agent during initialization, since move speed is related to the Movement script.
Or maybe there's another way to do it that i'm missing? Was wondering what is the best practice.
Keep your data where it belongs.
NavMeshAgent consumes your 'speed' as input, its not his job to store it.
Movement script makes more sense, or even better a PlayerConfig:ScriptableObject to set the initial value.
But definitivelly keep on Movement script, its job description is on its name. Imagine the player now have a buff or a curse that make it faster/slower, you would change the Movement script for it (and the movement will update the NavMeshAgent).
Related
I have been working on my own kinematic character controller for a while, but only recently learned that one should consider updating its position and rotation using Rigidbody.MovePosition and Rigidbody.MoveRotation instead of directly modifying the Transform component, which is what I am doing now. While my controller works fine, and does not cause any noticeable performance impact in my small games, I want to better understand the benefits of manipulating the Rigidbody component, and especially how this all works within FixedUpdate instead of Update.
To be clear about the supposed impacts on performance, Unity's manual on 2D rigidbodies says:
Any Collider 2D component added to the same GameObject or child GameObject is implicitly attached to that Rigidbody 2D. When a Collider 2D is attached to the Rigidbody 2D, it moves with it. A Collider 2D should never be moved directly using the Transform or any collider offset; the Rigidbody 2D should be moved instead. This offers the best performance and ensures correct collision detection.
Right now, my basic controller loop looks like this in the Update method:
Read the user's input velocity
Modify the controller's velocity based on this input (this velocity is distinct from Rigidbody.velocity)
Using Physics queries, sweep the controller's body against the appropriate collision layers by velocity * Time.deltaTime
Pick a collision resolution position based on a set of rules
Set the controller's Transform.position to this resolution position
I also have a method that moves the controller using Transform.Translate if no collision detection is needed.
As you can see, though my controller GameObject has a kinematic rigidbody attached to it, I never actually use it for anything. Unity's documentation on kinematic rigidbodies is conflicting, stating here:
Note: MovePosition is intended for use with kinematic rigidbodies.
but also here:
If isKinematic is enabled...The rigidbody will be under full control of animation or script control by changing transform.position
I am also unsure about how to manually check for collisions within FixedUpdate, as I have read that FixedUpdate can be called more than once per frame. Frankly, I thought FixedUpdate was only supposed to be used with dynamic rigidbodies to simulate real physics, and thus have only used this method for simple manipulation of those kinds of rigidbodies.
And then Rigidbody.MovePosition states that
2D rigidbodies have a fixed limit on how fast they can move therefore attempting to move large distances over short time-scales can result in the rigidbody not reaching the specified position during the next physics update. It is recommended that you use this for relatively small distance movements only.
What if my character needs to move a very large amount? Do I just set Rigidbody.position directly?
I guess I am trying to figure out how I can reconcile all of this logic to conform to what Unity says is best for performance. Perhaps I need to combine Update and FixedUpdate, but ultimately I am just hoping to receive some clarification and guidance regarding all of this.
I truly apologize for I have no code to offer here.
I am completely stumped, I’m still a coding noob and trying to run a simple exercise to test a game mechanic idea via prototype.
I’ll use a simple example:
2 players vs. 2 AI enemies
both enemy ai have 400 points of health
both human players have guns that do 20 points of damage per trigger
press.
both enemies are dead after a quick battle.
I want to reward the player who did the most damage to the enemies.
This is what I am trying to achieve:
How do I go about detecting, which player, did the most damage to the enemy AI?
Any help would be appreciated, once I can grasp the concept of how to even go about doing this, I can then move forward on how to code it.
Thanks.
The question is too general - there are a lot of ways to do this. Let's stick to OOP: let's make the "damage" object (script, class), which contains the following info: damage amount, player id. Wheh player hits trigger, lets assume, the bullet prefab is instantiated. It has a script (MonoBehaviour) on it, called "DamageContainer". When you instantiate a bullet, you also create your "damage" object, set correct values, and put it into bullet's "damage container". Then, when bullet collides with enemy, you get this info from bullet. Damage amount you use to reduce enemy's health. For counting damage, you need the counter itself. It can be a static class, a scriptable object, singleton, or something else. Let's use a static class, which is not the best practice, but simplest one. You need a simple static class, called "DamageCounter", and containing two public fields: Player1Damage and Player2Damage. When bullet collides with enemy, you need to add dealt damage to proper field of "DamageCounter", depending of damage.PlayerId field.
And don't forget to reset static class values on start of each battle.
I use cannon.js to simulate firing bullets. The bullet passed through the object without collision. I know this is because the speed is too fast. The bullet passes through the object at the interval of two frames. Is there any way to avoid this situation
player and object both have colliders and rigidbodies, object has position and rotation locked, player has only rotation locked. When the player goes to the blocks, the player goes through the blocks, although they do give a bit of resistance. To move the player im setting the rigidbody's velocity, and doing that in FixedUpdate.
i have no idea why this is happening, any ideas?
main part of the code is:
rigidBody.velocity = new Vector3(direction.x, rigidBody.velocity.y + (-Gravity * Time.deltaTime), direction.z);
(direction is determined by the WASD keys, and i'm using my own gravity)
First of all, you do not need to multiply the velocity by time.DeltaTime, because you are moving your object in the FixedUpdate() method; Which uses fixed time intervals since the physics engine does not run in sync with the regular game engine. Also, both objects do not need rigidbodies in order to collide with one another. I suggest looking at your collision matrix in settings and verifying that everything you need collision for is checked correctly. As others have said as well, check your kinematics on the rigidbody.
A last suggestion for working with your own gravity. Do not change the actual gravity value of the game engine. It is typically recommended that you use a multiplier variable and apply it to the constant gravity already set by the physics engine. If you are completely editing the gravity, than maybe consider using a character controller instead.
I guess it has something to do with what the documentation says "In most cases you should not modify the velocity directly, as this can result in unrealistic behaviour".
Try to use AddForce() or similar functions to alter the properties of the rigid body. Colliders etc will then work as expected.
I'm trying to make a projectile shooting system, but the Sweep Result is empty. I need it to see whether or not the projectile hit the bone 'head' and to see the hit location.
I made sure that I have a sweep collision on the projectile movement and the character movement.
Here is the overlapping event with the server event handling the ProjectileDamage:
https://blueprintue.com/blueprint/v9gzb-uf/
(Scroll up to see the OnComponentBeginOverlap Event)
The actual system works, but the sweep result is empty.
Thank you in advance
Physics or Projectile Movement
Use OnComponentHit, not OnComponentBeginOverlap, if using physics or a projectile movement component.
OnComponentHit
Event called when a component hits (or is hit by) something solid. This could happen due to things like Character movement, using Set Location with 'sweep' enabled, or physics simulation. For events when objects overlap (e.g. walking into a trigger) see the 'Overlap' event.
For collisions during physics simulation to generate hit events, 'Simulation Generates Hit Events' must be enabled for this component.
When receiving a hit from another object's movement, the directions of 'Hit.Normal' and 'Hit.ImpactNormal' will be adjusted to indicate force from the other object against this object.
NormalImpulse will be filled in for physics-simulating bodies, but will be zero for swept-component blocking collisions.
OnComponentBeginOverlap
Event called when something starts to overlaps this component, for example a player walking into a trigger. For events when objects have a blocking collision, for example a player hitting a wall, see 'Hit' events.
Projectile Movement
If using Projectile Movement Component, you can also use OnProjectileStop event.
Verify hit is impacting a skeletal mesh
You'll only get a Bone Name in the hit result if you are impacting a skeletal mesh.
Example Project
To see an example of a physics impact and a projectile movement impact hitting a skeletal mesh and returning a bone name, see this example project.
I now figured out how to fix my issue.
I just had to set the the object type, from the character, from 'Pawn' to World Dynamic. Now the projectile also has a Hit Result.