SetAllDirty() not working at runtime in Unity? - unity3d

Edit:
After doing a little more debugging I found that it doesn't work only when I start the game and have the panel/canvas that it sits on disabled. If I have the panel/canvas enabled the whole time then it redraws correctly. However, this obviously isn't a proper solution because I can't show the results before the end of the quiz. I need the panel to be disabled so that I can show it later after the end of the quiz.Is there a reason this is happening? How can I fix this?
End Edit
So I found a script on GitHub that basically creates a UI polygon. It works great in the Editor, however, I want to modify it at runtime. From everything I read all I need to do is call the method SetAllDirty() and it will update the MaskableGraphic and Redraw it. However, whenever I call it, nothing happens. SetVerticesDirty() also did not work. Can someone see where I am going wrong here.
All I am doing is calling DrawPolygon and giving it 4 sides, and passing a float[5] I modified it so that right after I finish setting up my new variables I call SetAllDirty()
Something like this:
public void DrawPolygon(int _sides, float[] _VerticesDistances)
{
sides = _sides;
VerticesDistances = _VerticesDistances;
rotation = 0;
SetAllDirty();
}
Like I said, it works fine in the editor(not runtime), and I am also getting all the values passed to the script correctly(during runtime), but it is not redrawing. As soon as I manipulate something in the inspector it will redraw to the correct shape.
The rest of the script is posted here:
https://github.com/CiaccoDavide/Unity-UI-Polygon/blob/master/UIPolygon.cs
This is the method that I call DrawPolygon from on a Manager script. I see in the log that it prints out the statement, Quiz has ended.
void EndQuiz()
{
Debug.Log("Quiz has ended.");
QuizPanel.SetActive(false);
ResultsPanel.SetActive(true);
float[] Vertices = new float[5] { score1, score2, score3, score4, score1};
resultsPolygon.DrawPolygon(4, Vertices);
}

Related

How to get info about completion of one of my animations in Unity?

I have monster named Fungant in my 2D platform game.
It can hide as mushroom and rise to his normal form.
I try to handle it in code, but I don't know how to get information about finished animation (without it, animation of rising and hiding always was skipped).
I think the point there is to get info about complete of the one of two animations - Rise and Hide.
There is current code:
if (
fungantAnimator.GetCurrentAnimatorStateInfo(0).IsName("Fungant Rise")
)
{
fungantAnimator.SetBool("isRising", false);
isRisen = true;
fungantRigidbody.velocity = new Vector2(
walkSpeed * Mathf.Sign(
player.transform.position.x - transform.position.x),
fungantRigidbody.velocity.y
);
}
if (fungantAnimator.GetCurrentAnimatorStateInfo(0).IsName("Fungant Hide"))
{
fungantAnimator.SetBool("isHiding", false);
isRisen = false;
}
I try this two ways:
StateMachineBehaviour
I would like to get StateMachineBehaviour, but how to get it?
No idea how to process this further.
AnimationEvents
Tried to do with animation event but every tutorial have list of functions to choose (looks easy), but in my Unity I can write Function, Float, Int, String or select object (what I should do?).
I decided to write test() function with Debug only inside, and create AnimationEvents with written "test()" in function field, but nothing happens.
Same as above, no more ideas how to process this further.
I personally would use animation events for this. Just add an event to the animation and then the event plays a function after the animation transition is finished.
For more information on how to use animation events you can click here.
This post may also help you to add an event when the animation is finished.
I hope this answer helps you to solve this problem.

Unity: Trying to load and run an fbx animation

I am trying to load an animation from an fbx file and have it play on a GameObject:
TestObject.AddComponent<Animation>();
animation_handler = TestObject.GetComponent<Animation>();
walking_anim = Resources.Load("fbx_anims/walking_anim_test", typeof(AnimationClip)) as AnimationClip;
if(walking_anim == null)
{
Debug.Log("walking anim not found");
}
walking_anim.legacy = true;
animation_handler.AddClip(walking_anim, "walking");
animation_handler.wrapMode = WrapMode.Loop;
In the game loop, I tried using this:
if (Input.GetKeyDown(KeyCode.W))
{
if (!(animation_handler.IsPlaying("walking")))
{
animation_handler.clip = walking_anim;
animation_handler.Play("walking");
}
}
It doesnt give any errors, yet it doesn't work either. Anything I'm missing?
EDIT: For clarification: The model stays in the default T-Pose, after pressing 'W'. After inserting Debug.Logs at different points, I can confirm that the Play function is getting called only once, after which IsPlaying always returns true. Yet the "playing" animation causes no visual changes in the model (yes, the bone names are the same).
You don't want to use the Animation component, it is an old legacy component that has been replaced by the much improved Animator component. There are a lot of good posts on the Internet on how to use it - no need to repeat it here. The important steps are:
Add the Animator (not Animation) component to the model.
Create an "Animator Controller" in your project and add the clips (like the "walking_anim"). Here you can have a lot of different clips and tell Unity how to interpolate between them by using different parameters.
Add the "Animator Controller" to your "Animator" component.
Add an "avatar" of your model (usually created when the model is imported).
By code alter the parameters of the Animator Controller to tell it which animation clips to play.
It may look like a lot of steps, but it is not so hard and you will quickly have a walking, running, jumping creature on your screen. Good luck!

Change motion using script in Unity Editor

Hi how do we change motion in an AnimatorController using script in Unity Editor?
The red highlight is the one I'd like to change, but using script
My use case is to copy animations from one object, process the animation e.g. adding offset rotation, then add to another object. Since my object has many child objects, I need to create a script to automate this.
Changing the AnimatorController via editor scripts is always quite tricky!
First of all you need to have your AnimationClip from somewhere
// somewhere get the AnimationClip from
var clip = new AnimationClip();
Then you will have to cast the runtimeAnimatorController to an AnimatorController which is only available in the Editor! (put using UnityEditor; at the top of the script!)
var controller = (AnimatorController)animator.runtimeAnimatorController;
Now you can get all its information. In your case you can probably use the default layer (layers[0]) and its stateMachine and according to your image retrieve the defaultState:
var state = controller.layers[0].stateMachine.defaultState;
or find it using Linq FirstOrdefault (put using System.Linq; at the top of the script) like e.g.
var state = controller.layers[0].stateMachine.states.FirstOrDefault(s => s.state.name.Equals("SwimmingAnim")).state;
if (state == null)
{
Debug.LogError("Couldn't get the state!");
return;
}
Finally assign the AnimationClip to this state using SetStateEffectiveMotion
controller.SetStateEffectiveMotion(state, clip);
Note however that even though you can write individual animation curves for an animation clip using SetCurve unfortunately it is not possible to read them properly so it will be very difficult to do what you want
copy animations from one object, process the animation e.g. adding offset rotation, then add to another object.
You will have to go through AnimationUtility.GetCurveBindings which gets quite complex ;)
Good Luck!

Unity3D Text not changing after being set in Start()

I have a Canvas (World Space Render mode) with a Text and a Button component displayed in a tridimensional space (it's a VR app). The canvas instantiated at runtime using a prefab.
I get a reference to the Text object using:
_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent<Text>();
I want to update the text at run-time using:
void Update()
{
_codeTextLabel.text = _codeText;
}
where _codeText is just a variable I update based on specific events.
The problem is that the Text gets updated only the first time, but if I try to change the variable nothing happens. I have tried several combinations and also the method _codeTextLabel.SetAllDirty() but it doesn't work.
The only way to update the text is to re-instantiate the prefab.
Are you instantiating your prefab before setting the values. If you are storing the _codeTextLabel reference before instantiating then your reference will point to the prefab not the runtime object. I can't see the rest of your code, so I can't say for sure. (I would have asked as a comment, but as I'm new I don't have the reputation to do so)
edit: I did a test to try and recreate your problem. I made the following script and it appears to work as expected. CanvasPrefab is a worldspace canvas with a UnityEngine.UI.Text component attached. (The script is attached on an empty game object in the scene btw)
public class ChangeText : MonoBehaviour
{
public GameObject CanvasPrefab;
private GameObject runtimeCanvas;
public string runtimeText = "something";
private Text textRef;
// Start is called before the first frame update
void Start()
{
runtimeCanvas = GameObject.Instantiate(CanvasPrefab);
textRef = runtimeCanvas.GetComponentInChildren<Text>();
}
// Update is called once per frame
void Update()
{
textRef.text = runtimeText;
}
}
as long as you did something wrong, It works absolutely so I guess there are several cases
Failed to do "_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent();"
'_codeTextLabel' lost reference from 'GameObject.
Doesn't change runtimeText' change at all
Subscription of events failed I mean, your updating scripts doesn't get proper event to update that text.
Without codes, this is only thing I can guess for yours so please check above I hope there is case among above.

UNITY 2D - Can't change Child's position

I have created a project and put a character in it, a Ninja. I drew every part of his body and put them together into one organized gameObject. It is organized as this.
Ninja Organization
NOTE : The Left_Arm GameObject has a parent so it can be rotated by the shoulder like a real arm
Now here comes the problem. I've searched and searched for hours and haven't found a solution to something that is surely so simple and dumb. In a script, I try to move the Left_Arm parent for a little animation. Here's the script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NinjaShooting : MonoBehaviour {
[Header("GameObjects")]
public Transform leftArm;
public Transform rightArm;
[Header("Other")]
public bool shooting = false;
// Update is called once per frame
void Update () {
Debug.Log(leftArm.localPosition);
leftArm.localPosition = new Vector3(100, 100, 100);
Debug.Log(leftArm.localPosition);
shooting = false;
}
}
The public variables are all assigned and everything, there are no errors in the console, but the line leftArm.localPosition = new Vector3(100, 100, 100); doesn't seem to do a thing to my character.
Here's is the Console after running it : Image
The console seems alright. The start position is (-0.3, 0.2, 0) and after leftArm.localPosition = new Vector3(100, 100, 100); the position is debugged as (100, 100, 100) as it should be. But the position changes in the inspector, nor in the game window...
Additionnally, the starter position is debugged every frame, but it shouldn't. So I assume that my position isn't taken into account or something.
I've done this so many times, and always has worked.
I even tried with a new project and recreated it, and there, mysteriously, it worked. So there is someting wrong with my organization or something. Sorry if this is a stupid question.
Thank you in advance
PS : Here is an image of the script in the editor, just in case there something wrong with that : Image
PS : The script is a it weird because I simplified it :). But this doesn't work too
This issue is likely caused by an Animator controller "locking" properties that are not actually part of its Motion. In this case, it is "locking" the Transform's position. Unity does not report any warnings or errors when you try to modify those properties, even if they are being controlled by an animation.
The typical offender is the Write Defaults property being set to true for your Animation States in your animation controller. Have a look here at the documentation for what Write Defaults does, and it will make more sense to you. I suggest changing it to false for all animation states that do not need it.