I am using the A* graph package that I found here.
https://arongranberg.com/astar/download
it all works well in scene view and I was able to set the graph to treat walls like obstacles.
However once I start the game the canvas scales and the graph's nodes no longer align with the walls.
this is really messing up my path finding. If anyone has any ideas how to fix this that would be much appreciated. I tried parenting the graph to the canvas but it still doesn't scale.
Kind regards
For anyone struggling with this what we did is edited the script of the A* code, in the update function we just got it to rescan once. This means that once the game started and all the scaling had taken place the graph re adjusted its bounds. This is probably not the most proper way but it only took four lines and worked for us.
private bool scanAgain = true;
private void Update () {
// This class uses the [ExecuteInEditMode] attribute
// So Update is called even when not playing
// Don't do anything when not in play mode
if (!Application.isPlaying) return;
navmeshUpdates.Update();
// Execute blocking actions such as graph updates
// when not scanning
if (!isScanning) {
PerformBlockingActions();
}
// Calculates paths when not using multithreading
pathProcessor.TickNonMultithreaded();
// Return calculated paths
pathReturnQueue.ReturnPaths(true);
if (scanAgain)
{
Scan();
scanAgain = false;
}
Related
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!
I've been searching stack overflow and the internet for a bit trying to search for a solution to this issue, everytime i try to use OnBecameVisible() or OnBecameInvisible() or TestPlanesAABB to check if the object is not visible through the wall, the camera can still see the object through a solid wall.
Video of the problem here:
https://youtu.be/3HiEugm6On8
As you can see, if i'm looking at him he stops moving, if i turn around and he "unloads" or "becomes invisible" he moves closer, but if i go around a corner still looking in his direction he stops moving as if i can see him and there is no wall there, this is what i'm looking to solve
it's an enemy that roams around, and i want him to only move if i cannot see him, which i thought would be fairly simple, but alas it seems not to be as simple as i thought
my current code is basic:
public bool IsSeen = false;
public void OnBecameVisible()
{
Debug.Log("I can now see you");
IsSeen = true;
}
public void OnBecameInvisible()
{
Debug.Log("I can't see you");
IsSeen = false;
}
this is attatched to the object that i wish to detect / not detect through walls, which i do believe checks if the object is viewable by the camera that i choose.
does anyone have any ideas as to how i can fix / achieve this?
As already mentioned the general "problem" with Renderer.OnBecameVisible is
Note that object is considered visible when it needs to be rendered in the Scene. It might not be actually visible by any camera, but still need to be rendered for shadows for example. Also, when running in the editor, the Scene view cameras will also cause this function to be called.
So its not really usable for you.
is there a simple way to raycast the whole screen?
Unfortunately not really :/
You can a bit avoid this using GeometryUtility.CalculateFrustumPlanes in order to get the four planes of the camera frustrum. Then you can check whether the object is actually inside the frustrum using GeometryUtility.TestPlanesAABB
var cam = Camera.main;
var planes = GeometryUtility.CalculateFrustumPlanes(cam);
var objCollider = GetComponent<Collider>();
if (GeometryUtility.TestPlanesAABB(planes, objCollider.bounds))
{
Debug.Log("I am inside the camera frustrum!");
}
else
{
Debug.Log("I am out of sight...");
}
However, this still does not cover any other object being in front of the target object and therefore actually covering it.
You would need to define exactly what visible means (e.g. any portion of the mesh? Is the center of the object enough to test? etc).
For e.g. testing only the center of the object you could use a Physics.Linecast like e.g.
if (GeometryUtility.TestPlanesAABB(planes, objCollider.bounds))
{
Debug.Log("I am inside the camera frustrum!");
if(Physics.LineCast(cam.transform.position, objCollider.GetComponentInChildren<Renderer>().bounds.center, out var hit)
{
if(hit.gameObject != objCollider.gameObject)
{
Debug.Log("..but something else is in the way..");
}
else
{
Debug.Log("Now you see me, muhaha!");
}
}
}
If you want it to be more precise and track of any part of the mesh is visible then it actually gets tricky. You would need to raycast multiple key points of the bounding box (e.g. each corner, centers of the edges etc) depending on your needs.
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!
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.
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);
}