Attach an Animator to a clone GameObject - c#

I am instantiating game objects by a For loop:
Dragon Manager script:
//Instantiate prefab
enemyDragons2[i] = (GameObject)Instantiate(enemyDragonStandIn,
PlaceToSpawn - Vector3.forward * 20.4f, Quaternion.identity);
//Attach script
enemyDragons2[i].AddComponent<SeekChase>();
In the SeekChase script, I have at the beginning:
static Animator anim;
and in the Start I have:
anim GetComponent<Animator>();
In the Unity editor I have everything set up: State Machine ,Parameter, Transitions and Conditions, to play from one animation, and then to another when a condition is met.
I thought that each clone game object would have the static Animator and the anim GetComponents() parts attached, but I have continuously received the error: "No Animator attached to the Clone game Object, but a script is trying to access it". This points to ,(place of the error(s):
anim.SetBool ("isIdol",false);
anim.SetBool ("isTurning",true);
I also tried to add to SeekChase:
**public**static Animator anim; (though it dosent seem like I should have to do this.)
In the Dragon Manager script( where the objects are instantiated) I tried adding the line:
static Animator anim; (in the Start)
and
anim = enemyDragons[i].AddComponent<Animator>();
I recieved the error: "animator is not playing an animator controller"
But animations don't seem to play through code, just the default take, but not transition to the next("isTurning").It seems like I am missing something simple.
Any help will be appreciated.
Thank You.
============================================
EDIT/Solution
To begin. Unity should not let you continue if there is a level error, because it gives you a false sense of being about the functioning of things.
When I was testing, I was using ONE prefab, (of 6), to test animations on. They all were using the SeekChase script. So when I would press Play, I would always get the errors:
"No Animator attached to the Clone game Object, but a script is trying to
access it".
I sort of expected an error because the other instantiated objects were having their Animators accessed by the SeekChase script, though they did not have one. Since I was testing on one object that was being instantiated, and Unity allowed me to "Play", I did not think that that error was related to the functioning of my current animation problem.
With your suggestions, I was able to, in the State Machine, with transitions arrows attached, have the two animations play from one to the other ( this wasn't being done before). But, with the condition that I had to set the bool:
if(direction.magnitude < 10.0f)
{
// Animator Stuff####
anim.SetBool("isIdol",true);
anim.SetBool("isTurning",true);...
}
..... the second animation was not being played.
Then I thought about the persistent error, and decided to comment out SeekChase script being applied to the other game objects......and then the second animation it played!
Hopefully when I fix all the prefabs and insatiate them, all will function.
Thanks again.

First make enemyDragonStandIn as gameobject without instantiating with the animations working, then make that gameobject prefab, after that you can instantiate it with the rigth animations instead of adding them on runing time. Finally call on the instantiated object
anim.SetBool ("isTurning",true)

Related

Transition FPS Camera Animation from Idle to Walking?

So, I recently learned how to animate certain objects, but I don't know how the code works.
I learned the animator tab, where idle camera animation will transition from walking if I am holding my movement keys. I searched tutorials on youtube and google, but all I can find are animations found on models, not actually on the camera.
If I used that logic on a camera, nothing actually happens, and I don't know what to write.
I've set a bool, which is labeled "WalkingForward", because I have different animations on different movements.
When it is true, the forward walk animation will play, and if false, it turns back to idle animation.
The only thing I can't figure out is a code that will detect the "Horizontal" and "Vertical" movements to start playing the animation.
Here is the link of my animator controller tab https://imgur.com/a/euM9yFl , and I would really appreciate if someone has an idea.
You can handle/detect movement in the Update() method for a GameObject, then get the Animator for the Camera and set the Animator parameters.
See Unit Animation Parameters Docs for more info, but the general idea is something like this:
// Update method attached to wherever you want to detect movement
void Update()
{
// isMovingHorizontally and iMovingVertically are not defined here
// They could either be based off the speed/momentum of the GameObject
// Or the input from the player
var isMovingHorizontally = isMovingHorizontally();
var isMovingVertically = isMovingVertically();
animator.SetBool("MovingHorizontally", fire);
animator.SetBool("MovingVertically", fire);
}

Unity: Enemy objects passing through box collider on edges of background

I'm developing a simple 2D Unity game (which I'm very new to so sorry if this is a silly question!) in which my player can eat its enemies by colliding with them. This works fine as I'm just selecting the "is trigger" component for the enemies and using this code in my Player class:
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("Hit detected");
Destroy(other.gameObject);
transform.localScale += new Vector3(x, y, z);
}
However, this means the colliders placed around the border of my background image aren't stopping the enemies. What's the best fix for this?
I don't understand very well your question. However it seems that your collisions are not working. So, remember that for have collisions actually taking place in your game you need to use colliders and that one of the two elements participating in the collision need to have the rigidbody component.
That will make the physics work in the engine, which triggers dont.
To check if that works you can debug with:
// called on collision
void OnCollisionEnter2D(Collision2D col)
{
Debug.Log("OnCollisionEnter2D");
}
From what I understood, you want only to detect triggers between the player and the enemies, but you still want these to collide with physic objects in your scene, such as background colliders.
One possible way to achieve this is to create a child object for the player object with a collider component with the trigger option set, and attaching a script to it to handle the triggers. Then, with the use of layers to group your player and enemy objects, you can uncheck the collision between them following: Edit -> Project Settings -> Physics 2D: "Layer Collision Matrix".
You can assign a script to any enemy, checking the distance with the player in each frame. Then you can Uncheck "is trigger"
Vector2.Distance

Why does my script, which aims to remove gravity when the game starts, not work?

I'm trying to create a script in Unity wherein the gravity will go to zero when the game starts. The problem is, the gravity was still there after I launched the game.
This is for a Unity3D game. I've already tried to change the variable name, add using System; and moved my script to the top of the Rigidbody component, but none of these things worked.
public class PlayerGrav : MonoBehaviour
{
public Rigidbody rb;
void Start()
{
rb.useGravity = false;
}
void Update()
{
}
}
I expected the gravity to be removed when the game launches, but in the actual output the gravity still remained, and the cube still fell downwards.
create a new scene
create a new cube
add rb = this.GetComponent<Rigidbody>() to your start function in your PlayerGrav script
attach your PlayerGrav script to the new cube
Hit play, and take look at the "use gravity" property from your new cube's inspector window (make sure the inspector isn't locked to other game object)
If the above tryout succeeds, then you need to check the other code/objects in your original scene. If there are massive other objects in your original scene, then I will suggest disable other objects first, and re-enable them back group by group to see which object/monobhevaiour is causing the issue.
I know this is an old question but I looked forever trying to find an answer to this. I am new to unity so it took me a long time to figure this out but I am using a Rigidbody 2d so this is what worked for me
gameObject.GetComponent<Rigidbody2D>().gravityScale = 0;

Checking Animator on Unity script only work on first Object

Let me explain the question first :)
I have a hero and an enemy. It is a fighting game. Both hero and enemy have idle, block, punch and getHit animations and states in the Animation Controller. The hero and enemy have scripts attached to them. The hero is controlled by player and then enemy is controller by AI.
Now I attach the script to hero first and then the enemy. Now when the enemy punches and if hero is not defending the hero takes a hit. But if the enemy is not blocking and the hero hits the enemy doesnt take the hit. This is because the script was attached to hero first.
Now if I remove the script from both and attach the enemy script first to enemy and then attach the hero script to hero. The wiseversa is true. In the enemy the hits will be registered and on the hero the hits wont be registered.
I am not sure why this is happening and I have tried different things and still the problem persists.
I also tried looking everywhere online for solution but none of them addressed my concern.
Thanks :)
below is the enemy script that checks is enemy can take hit
void Update () {
myTick++;
currentTick = myTick;
GameObject player = GameObject.Find("theDude");
Animator pAnim = player.GetComponent<Animator>();
//Getting Hit
if (pAnim.GetBool("tIsPunching"))
{
if (anim.GetBool("bEnemyIsDefending") == false)
{
Debug.Log("enemy got hit");
anim.SetTrigger("tEnemyGotHit");
anim.SetBool("bEnemyIsDefending", true);
}
}
}
And here is the hero script that checks if hero can take hit.
void Update () {
totalTime += Time.deltaTime;
GameObject enemy = GameObject.Find("Enemy");
Animator eAnim = enemy.GetComponent<Animator>();
//Getting Hit
if (eAnim.GetBool("tEnemyIsPunching"))
{
if (anim.GetBool("bIsDefending") == false)
{
Debug.Log("player got hit");
anim.SetTrigger("tGotHit");
}
}
}
Instead of get object I used to have a public GameObject and attached the hero and enemy in the respective classes. But It doesnt make any difference.
I think your problem lies in your use of the triggers tEnemyIsPunching and tIsPunching. Triggers get reset whenever they cause a transition to occur
(see: https://docs.unity3d.com/Manual/AnimationParameters.html).
In your case tIsEnemyPunching or (tIsPunching) is getting reset in the same frame as it gets set. Here is an example of what one update loop may look like in your game if the hero script is added first:
Hero Update()
Check if enemy is punching
He is not, so don't do anything
Enemy Update()
Punch! Set 'bIsEnemyPunching' = true
Animation Update()
bIsEnemyPunching is true so transition to the punching animation
reset bIsEnemyPunching = false
On the next update let's look at what happens in the hero update:
Hero Update()
Check bIsEnemyPunching
bIsEnemyPunching was reset in the previous frame, so it is false
Since the enemy isn't punching don't do anything
So Hero never sees the punch because bIsEnemyPunching got reset before Hero had a change to check it.
This is why the order of adding the scripts matters. Whichever script updates first is able to punch because the second script will see the trigger before it gets reset. However, the second script to update will never be able to punch because the trigger gets reset before the other scripts gets a chance to update.
One solution is to check the name of the animation state instead of the trigger value.
static int punchStateHash = Animator.StringToHash("Punch");
AnimatorStateInfo enemyState = eAnim.GetCurrentAnimatorStateInfo(0);
if (enemyState.nameHash == punchStateHash){
//The enemy is punching!
}
Alternatively, whenever a punch is triggered just call a function on whichever character is getting punched. So when the enemy punches the hero the Punch(...) function on the enemy should call TakePunch(...) on hero (or whatever you want to call those functions). The hero then checks his own state to determine if he is blocking.
Additional Note
You should avoid using the following code in an update function:
GameObject player = GameObject.Find("theDude");
Animator pAnim = player.GetComponent<Animator>();
These functions are very slow because Unity must search all objects for the one called theDude and then search all it's components to find the animator. Do this once and save off the result.

Magnet script issues in Unity

I'm trying to make a magnet PowerUp in Unity. I used this script, which I attached to the coin GameObject:
public GameObject attractedTo;
private float strengthOfAttraction = 3f;
void FixedUpdate ()
{
Vector3 direction = attractedTo.transform.position - transform.position;
gameObject.GetComponent<Rigidbody>().AddForce (strengthOfAttraction * direction);
}
I have two problems :
1. Only newly spawn coins are attracted to the player
2. For some reason, the coins move only in straight lines, so most of them goes past the player
Anyone knows how this can be fixed?
Any help will be appreciated!
Major issue on your code. You have to recreate your procedure logic on how you make the coins get closer to the Player.
First Major problem is this.
void FixedUpdate() So on a fix amount of time per frame. You are trying to
Declare a Variable Vector3 : Vector3 direction = attractedTo.transform.position - transform.position;
So frame will recalculate and create a new pointer name direction then you try to find gameObject.GetComponent<Rigidbody>().AddForce (strengthOfAttraction * direction);
your Own Component in your gameObject. Then Call Addforce. AddForce. And you didn't even use time.deltatime.
Addforce Will push the rigidbody depending on the direction you input. So it will go straight. And you are doing this Every Fix amount of frame per sec.
First fix your procedure. My recommendation is this.
Use the Smooth Follow script. Made by Unity3D get your Reference there. It is also installed already in the script section in your Editor. If you are having problem finding it, go to this link and check he script.
Smooth Follow Script
[Update Answer]
For the 2nd Problem that only new coins is getting attracted.
Check all of this situations.
Your Player is newly spawned and your attractedTo variable is blank.
Non newly spawned coins should have referenced to the Player already, if not you have to tell all the coins that if you spawn the Player, they needed to be attracted to Player. -> Assign attractedTo when Player Spawned.
You can either Achieve that on Instantiate then find all GameObjects with TAG. Then getcomponent then assign attractedTo
Your non Spawned coins, doesn't have the Script Component.
Your non Spawned coins, is disabled.

Categories

Resources