When exit the state and return to it
the enemy is going to the player but stopping in the last known location of the player
every time the player come near him he go back
like the last distance the player and enemy had before he lost him
Here is a video of the bug
The code is a bit different to the course but not much i dont use public much in my project and i dont want to redo my code to adjust it to nathan hope you understand
I tried Reseting the path in enter in exit
i tried moving the navmesh agent to EnemyStatemachine and calling all from there
nothing seems to fix this bug
watch the video and see
My Movement Script dont mind the knockbacks i do stuff different a bit with the coding more organized
i didnt like everything on the StateMachine
@Brian_Trotter I dont know if you have any ideas on this one as i know we had a similar issue with knockback being the cause but the enemy is not attacking in this case.
I cant think of anything that would cause this other than in a GOAP project where the navmesh and the actual gameobject had a difference of opinion to where the position was.
@babi6k Have you checked the components in a paused state to see the position of them to see if the above is occuring?
When i enter the state again the agent.destination stay the same as before thats why have the problem
i did a Debug.Log for it
After many Debugs of different things i found that the agent.desiredVelocity when come back to the state and is in the last distance from player to enemy
then it equals to 0 and thats why it isnt going anywhere
I still don’t know how to fix it
Does the normal project have this bug too ?
Hey, @babi6k, you’ve made many modifications to the course code, and I don’t think there’s a straightforward way to help you. A couple of things stand out as “bad” practices and, in a larger/more complex project, will create a lot of headaches if you implement them in that way.
In your EnemyChaseState.cs - Enter Method . You are using GetComponent for all the shared elements from all the states. Why is this a bad practice? Because every time you switch states, you create memory-intensive calls to objects that do not change (and should be cached). Any reference to a component is handled in the course by a single script, EnemyStateMachine.cs. This creates a clear way for all the calls we make in any state. Every time you “switch” states, you are destroying any information that was in them ( you create more garbage collection)
You created a new script that is called “Movement.” Why? In the course, all the shared methods are part of the “EnemyBaseState.cs”. This gives ALL the states direct access to any functions that are in there (ex: “Move,” “IsInChaseRange,” etc.) without having to assign a special script just for them.
I’ve made a quick diagram of how I understood the system and its benefits (please correct me if I’m wrong)
I would recommend you revisit the initial lectures about what and how the State Machine architecture is implemented in the course and revert all those changes you made in each individual states ( Constructors & Inheritance | GameDev.tv )
I think the issue may be the line I’ve highlighted in the quoted method above.
Ideally, what we want to do is tell the NavMeshAgent what it’s new position is rather than trying to set it’s velocity directly.
Try replacing that line with:
Ok thats good to know
i thought i was organizing it to be by class dependent
i made a mover/movement script for controling the CharacterController/ rigidbody before
i will move everything to be cached only in the statemachine in player and in enemy
so i have access from the statemachine
i thought i am writing the code in a way like we did in the rpg courses
each class in charge of its own stuff
So you’re aware, many students will be working to transition what is learned in the Third Person Character course into the RPG course. Some of the changes Yanev was making are in line with my upcoming 3rd Person to RPG Integration guide.
My actual suggestion in the migration guide will be to have a clean copy of the RPG project, a clean copy of the Third Person Project, and then clone the RPG project and make the changes to integrate the 3rd person controller.
Refactoring back is up to you, and I never want to discourage customization or alterations to the course project. The reason that I recommend students who do so keep a clean copy that closely tracks the course project is simply that it makes it infinitely easier to troubleshoot when something goes wrong. If you have an example of something going right, you have something to compare and often times you’ll find the issue yourself just in the comparison. (For example, I went to my copy of the code and compared the Move method in your Mover to my own Move code in the EnemyBaseAction, and was able to spot the likely culprit).
Hey @Brian_Trotter, thanks for the heads-up. I can see the similarities between systems ( ActionScheduler has the same function as SwitchStates). Each has its benefits, disadvantages, and use cases. Based on my current level of understanding, my suggestion was solely on the current context: we create a new state every time we switch states. Please correct me if I misunderstood this.
In the Rpg combat course, this is not an issue as those “states” (ex: fighter/mover / etc.) are initialized on start and will “remember” all the references, whereas here, we have to remake the calls every time we go back a state because of our usage of the word “new.” If we used a dictionary or list to create a cached version of all the states a player/Ai has and used those references when we switch states, that would have solved the issue.
Hey @babi6k, Yes, you are correct. As I mentioned in my comment to Brian, I think the current context and how the StateMachine is implemented creates an extra problem that needs to be addressed before you try to implement the RPG structure. However, as with everything game dev, there’s no “right” or “wrong” way to do something, and a problem will have multiple solutions or ways to go about it.
Yeah i understand now the problem and im fixing it
im leaving the Mover And animatorHandler and fighter i made
just caching them in the EnemyStateMachine and in the PlayerStateMachine
that way all will run smoothly and without extra Get Components
Also i will make them public but hide in inspector that way you just cached them from the script and dont need to drag them in
I actually have a trick for that, which allows you to both drag in references, or have them automatically set (I’ve been moving more towards pulling some things like the Animator off of the outer Gameobject to reduce clutter).
void OnValidate()
{
if(ForceReceiver==null) ForceReceiver =GetComponent<ForceReciever>();
if(Health==null) Health = GetComponent<Health>();
if(Animator==null)
{
Animator = GetCompnent<Animator>();
if(Animator==null) Animator = GetComponentInChildren<Animator>();
}
//continue with each component
}
Nope, Unity doesn’t like this construction one bit. [field: SerializeField] is doing something internally that is a bit different than [SerializeField]. Behind the scenes there’s a lot more going on as a backing field for the property is created, along with a getter and a setter. You’d need to return to a more classic construction:
[Header("Movement Speeds")]
[SerializeField] float walkingSpeed = 1.5f;
[SerializeField] float runningSpeed = 5;
[SerializeField] float targetingSpeed = 4f;
[SerializeField] float rotationSpeed = 10f;
public float WalkingSpeed=>walkingSpeed;
public float RunningSpeed=>runningSpeed;
public float TargetingSpeed=>targetingSpeed;
public float RotationSpeed=>rotationSpeed;