When animating a 2d object `Transform.Translate()` stops working - c#

I'm developing an enemy AI in a 2D Game that I'm working on. This enemy swims and I wanted to make a "floating effect" animation for the enemy, so I made an animation where the Y Axis of the game object bounces up and down.
I Use transform.Translate() to move the enemies in the game and it worked just fine until I made this animation. But, when the animation is playing, the enemy can't move in any direction.
public virtual void Move(float speed)
{
if (canMove)
{
transform.Translate(new Vector2(speed, 0) * Time.deltaTime);
}
}

Once you have a keyframe in any state of your animator for a certain property the animator will always overrule any changes done in a script because the animation updates are all done after Update. You could try to either move your code to LateUpdate.
Or in your specific case you do not want the x component of your position keyframed at all. Simply remove all the keyframes for the x (and z) component(s) of the position from the animations so only y has keyframes. This should solve your problem.
Alternatively use your movement script on a GameObject on a higher level in the hierachy as your Animator - meaning add a new GameObject, make the animated object a child of it and place your movement script instead on that parant object.

Related

Player Keeps Going Through the Wall

I have a game where map/background is made up of prefabs. My player and prefabs both have rigidbodies and colliders. Neither of them have is trigger checked and the prefabs have collision detection set as continuous dynamic. The player's collision detection is set on continuous. Each of the prefabs have a mesh collider and the individual walls of the prefabs have box colliders (none are set to is trigger). I keep trying to test it on my phone using Unity Remote 5, and every time I move the player it goes through the walls. If anyone has any advice on how to prevent my player from going through the walls, I would really appreciate it!
My movement script is:
public class Movement : MonoBehaviour
{
private Touch touch;
private float speedModifier;
void Start()
{
speedModifier = 0.01f;
}
void Update()
{
if(Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if(touch.phase == TouchPhase.Moved)
{ transform.position = new Vector3(transform.position.x + touch.deltaPosition.x * speedModifier,
transform.position.y,
transform.position.z + touch.deltaPosition.y * speedModifier);
}
}
}
}
It would really help to see your movement script however it sounds like you are moving player by manipulating transform.position or using rigidbody.MovePosition() without setting isKinematic to true. The documentation says;
If the rigidbody has isKinematic set to false, it works like transform.position=newPosition and teleports the object to the new position (rather than performing a smooth transition).
This behaviour will ignore the collision. Also you don't need rigidbody on every GameObject in the scene. 1 rigidbody on the player is enough to collide it with other objects.
depend on what I got from your question, when you are playing and the player hit the wall, it goes inside; so the problem might be the mass of the wall. if you must add a Rigidbody to the wall so you need to add more mass to the wall also edit the border of the box collider and make them reasonably a bit wider, otherwise if you dont need a rigidbody on the wall simply keep just the box collider and it will works good. hope this answer help you, and it will be better if you can explain more the situation using some pics.
Using the Rigidbody position or applying force tends to cause the Rigidbody to clip through other colliders. I recommend changing rigidbody.velocity instead of directly changing the position.

How come the Collider falls from the GameObject when a RigidBody is added?

I could really need some help with my GameObjects.
I am working on a game in which I want a pick-up Item to create a Physics Force explosion to blow away the enemies. I made a simple Bomb-Object to test this idea. I added a straightforward code, using a loop to collect all the colliders within its radius, to then addForce to these colliders. Now the code is working properly, but not all my GameObjects are reacting properly.
I looked into why this is, and I noticed that my Collider keeps falling away from the GameObject as soon as I add a RigidBody component to the object. The RigidBody is needed for the AddForce impact. When I remove the rb, the collider stays in place, but the object does not react to the Physics Force.
I added some images to illustrate what I mean:
Image of the Collider of the leaf sinking away..
Example image of objects which DO react to the AddForce.
I already tried to:
Copy/Paste all component settings from the reacting Cube and stone
Gameobjects to the Leaf Gameobject while disabling all other code
such as the c# scripts. The Collider & RB do not fall through the
floor but when Physics Force hits the Collider is blown away while
the GameObject keeps its position.
Try different GameObjects/Collider types.
Removed the water.
Play with amount of force/radius of the bomb.
Edited 'Tag' and 'Layerstyle' of GameObject.
The 'Explosion Code' is added below, however, I don't think the problem is in the code. I added the code to the Main Camera of my scene, and added a simple sphere as the 'bomb' GameObject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Explosion : MonoBehaviour
{
public GameObject bomb; //set the position of the explosion
public float power = 10.0f;
public float radius = 10.0f;
public float upForce = 0.0f;
private void FixedUpdate()
{
if (Input.GetKeyDown("space"))
{
print("space key was pressed");
Invoke("Detonate", 1);
}
}
void Detonate()
{
Vector3 explosionPosition = bomb.transform.position; //set the position of our explosion to the position of the bomb.
Collider[] colliders = Physics.OverlapSphere(explosionPosition, radius); //collects all colliders within the radius.
foreach (Collider hit in colliders) { //for each individual collider the following code is ran.
Rigidbody rb = hit.GetComponent<Rigidbody>(); //declare'rb' rigidbody. Get rb component from each collider
if (rb != null)
{
print("BOOM!");
rb.AddExplosionForce(power, explosionPosition, radius, upForce, ForceMode.Impulse); //add force to each collider
}
}
}
}
How do I make the Rigidbody, Collider and GameObject of the leaf hold onto each other like the standard 3D object 'cube', so that I can make these blow away with the Physics Force just like the other models?
Thank you for your time, I have been trying things and looking around on the Internet for hours now but can't seem to find any solution.
What happens if you add the rigidbody in stop mode and press play? Does it move away in a similar manner? This may, and is expected to happen, if your colliders intersect with each other. As soon as you add a rigidbody, they find themselves trapped in a serious collision.
If you don't want to modify the scene, you can fiddle with the collision matrix in project settings / physics

Creating an endless spinner in Unity

I want a gameobject spinning around its y-axis. This spinner should have a initial movement direction and when colliding with something, it should change its direction.
I created a little picture to show what I mean, but I want the behaviour for a 3D game.
So I just started with the rotation of the spinner,
public class Spinner : MonoBehaviour
{
[SerializeField]
private float movementSpeed; // speed when moving
[SerializeField]
private float rotationSpeed; // speed when rotating
private Rigidbody rigid;
private Vector3 movementDirection; // the direction the spinner is moving
private void Start()
{
rigid = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
transform.Rotate(0, rotationSpeed, 0); // rotate the spinner around its y-axis
}
private void OnCollisionEnter(Collision col)
{
// set new direction
}
}
How can I move the spinner, that it moves along a direction and whenever it collides with something, it changes its direction. It should never stop moving or rotating.
I would like to point out a few things:
The Unity Physics Engine will make collisions to absorb part of the force which moves your spinner, so unless you keep adding "artificial" forces to the spinner it will eventually stop.
The "air friction" in your scene will also reduce the force of your
spinner, so it will slow it down. You should add a material to the
spinner which has 0 Dynamic Friction
Based on the comment you left in #reymoss' answer, you may consider
to add the bouncy material to the walls, and not to the spinning
GameObject.
To sum up, the issue here is if you want a GameObject to bounce against a wall using the Physics Engine, the object will eventually stop, because some of the forces will be absorbed in each collision. That means you will need to keep adding external forces every time a collision takes place, to keep it moving endlessly.
Something you can try is,
1- Add a bouncy material to the walls and remove the dynamic friction of your spinner. In the following link you can learn about this:
https://docs.unity3d.com/Manual/class-PhysicMaterial.html
2- Add to the Spinner a Collider, so when it detects a collision with a wall (you can tag the walls as so for example) add an additional force to the spinner in the direction it is already moving, so it will compensate the energy lost during the collision.
void OnTriggerExit(Collider other) {
if(other.tag == "wall") {
rigidbody.AddForce(rigidbody.velocity.normalized * Time.deltaTime * forceAmount);
}
}
The idea is to let the Engine decide the direction of the Spinner after the collision with the wall, and as soon as the GameObject leaves the trigger, you add an additional force in the current direction.
Then you can play with the Bounciness of the wall's material and with the forceAmount, until your spinner moves as you have in mind.
Note: Since you will have 2 materials, one in the walls and another in the spinner, maybe playing with the Friction Combine and Bounce Combine you will be able to avoid the force lost during collisions, so you will not need to add the external force I mention in the second step. However I have never tried this.
Let me know if it works. I can't try myself the solution until I arrive home.
If you give the object an initial velocity, attach a collider, create and assign a Physics Material 2D to the collider (to apply bounciness), and attach Colliders to the walls, you can have it bounce around with minimal code.
private void Start()
{
rigid = GetComponent<Rigidbody>();
rigid.velocity = new Vector3(2f, 3f, 1f) // initialize velocity here
}

Script not working when animation is enabled

I am testing to make a cube move with a script. Also have a simple Roll animation for the cube which is supposed to activate whenever I move the cube.
But the cube doesn't move when the animation is 'checked' as active under the inspector tab. The cube only moves if I disable animation thus not even able to see if the animation works properly when I move the cube. The cube is imported from Blender to Unity. Please advice what I am doing wrong.
The script is as follows. It is a very simple and small test file thus I have attached my Unity and Blender files too at Dropbox for reference if that helps. Thank you.
Link to Unity Project:
https://www.dropbox.com/sh/cvpjf26i31o1ell/AABmLMqYV4tPiG7qruph2D4Ra?dl=0
Link to Blender model and animation:
https://www.dropbox.com/s/deowh3yk5wpse1u/box.blend?dl=0
Movement script for cube:
public float speed = 10.0F;
Animator anim;
void Update()
{
float translation = Input.GetAxis("Vertical") * speed;
translation *= Time.deltaTime;
transform.Translate(0, 0, translation);
Animating(translation);
}
void Animating(float v)
{
bool roll = v != 0f;
anim.SetBool("Roll", roll);
}
I've updated the project and put it back up on dropbox
https://dl.dropboxusercontent.com/u/9274763/MechanimTester%20v2.zip
I added a new emtpy gameobject and made the blender cube a child of that.
The TestScript is now attached to that new gameobject and controls its position.
The animation now only applies to the child object and so the animation is no longer
interfering with the position of cube.
(What was happening was that the animation was modifying the transform for the gameobject - now as its a child its not affecting its parent so it doesn't reset the position of the overall gameobject
Does that make sense ?
Garrett

My camera rotates with my ball when i have ball as a parent gameobject of camera. what should i do?

I'm using my camera as a child gameobject of my ball, so when I move my ball camera comes with him. But the problem is I'm using rigidbody.addForce(), so when ball rotates the camera rotates with it, too.
So what should I do not to rotate my camera but only move it with my ball?
void FixedUpdate()
{
rigidbody.addForce(Input.getAxis("Horizontal"), 0, Input.getAxis("vertical"));
}
There are several ways to solve this, I'll list a few.
The first, if you don't care if your ball rotates or not, you can just disable the rotation on the ball. If you open the Constraints section in the rigidbody component, you can freeze the rotation so that the ball won't rotate.
Alternatively, you can write a script that keeps the camera always oriented a certain way. Depending on if you want the camera to rotate around the ball on any plane depends on the way you would implement this.
The third option, which is cleanest, is to not have the camera be a child of the ball. A minimal component to do this would look like this:
public class TargetFollow : MonoBehaviour
{
public Transform Target;
public float DistanceFromTarget;
void Update()
{
transform.position = Target.position + new Vector3(0, 0, DistanceFromTarget);
transform.LookAt(Target);
}
}
Just drag your ball into the 'Target' slot in your component. Keep in mind, this is super bare bones. You may want to add more variables to better control the direction the camera should be from the ball, or perhaps something that grabs a snapshot of the direction and distance the camera is from the ball in the Start method.

Categories

Resources