|
Post by wewechoo on Feb 4, 2019 4:05:40 GMT
To provide a simple summary of what has happened thus far - I didn't really want the CTR stat system as I wanted every unit to act only once per turn, so I removed the entire system and made the Turn Order Controller arrange the order according to the SPD stat. And naturally, as the Haste/Slow Status Effect scripts also relied on the CTR stat to work its magic, I had to modify that as well. However, I had difficulties trying to do that. Rather, I understand the general idea of going about to accomplish it, but the details (the actual code itself) are still pretty hazy to me.
1. Determining the unit that the Haste Status Effect component was attached to when it has already been removed. In fact, this is my main problem at the moment – I can’t use the GetComponentInParent command to get the Stats component on the unit because the Haste Status Effect component has already been removed. I want the script to change the stats first before being removed, not change the stats after being removed, but I don’t know how to do that.
2. I also understand that another method involves retrieving the sender that sent out the notification, and from there, getting the game object that the sender belongs to, and modifying the stats from there, but I…..don’t really know the command to retrieve it.
Also, I’m not sure whether it’ll help, but this is my current HasteStatusEffect script. I’m not all too good at this sort of stuff so pardon me if the coding looks bad, or if I’m overlooking some obvious command that everyone already knows.
using UnityEngine;
using System.Collections;
public class HasteStatusEffect : StatusEffect
{
Stats myStats;
private void Start()
{
myStats = GetComponentInParent();
myStats.SetValue(StatTypes.SPD, myStats[StatTypes.SPD] * 2, false);
}
void Remove(object sender, object args)
{
Stats myStats = GetComponentInParent();
myStats.SetValue(StatTypes.SPD, myStats[StatTypes.SPD] / 2, false);
}
void OnEnable()
{
myStats = GetComponentInParent();
this.AddObserver(Remove, Status.RemovedNotification, gameObject);
}
private void OnDisable()
{
myStats = GetComponentInParent();
this.RemoveObserver(Remove, Status.RemovedNotification, gameObject);
}
}
Once again, thank you for taking the time off to look through my problem.
|
|
|
Post by wewechoo on Feb 4, 2019 10:09:43 GMT
Update: I tried to carry out what you suggested in your second method. I created a new script, HasteStatusController, and changed the HasteStatusEffect script such that it now sends out the notification for the HasteStatusController to increase the SPD stat when it is enabled, and the reverse when it is disabled. Here's the code for my two scripts:
HasteStatusController
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class HasteStatusController : MonoBehaviour {
void Awake() { Stats stats = GetComponent<Stats>(); }
void OnEnable() { this.AddObserver(HasteActivate, HasteStatusEffect.HasteBeginNotification, gameObject.GetComponentInChildren<HasteStatusEffect>()); this.AddObserver(HasteRemove, HasteStatusEffect.HasteEndedNotification, gameObject.GetComponentInChildren<HasteStatusEffect>()); }
void OnDisable() { this.RemoveObserver(HasteActivate, HasteStatusEffect.HasteBeginNotification, gameObject.GetComponentInChildren<HasteStatusEffect>()); this.RemoveObserver(HasteRemove, HasteStatusEffect.HasteEndedNotification, gameObject.GetComponentInChildren<HasteStatusEffect>()); }
void HasteActivate(object sender, object args) { Stats stats = this.GetComponent<Stats>(); stats.SetValue(StatTypes.SPD, stats[StatTypes.SPD] * 2, false); }
void HasteRemove(object sender, object args) { Stats stats = this.GetComponent<Stats>(); stats.SetValue(StatTypes.SPD, stats[StatTypes.SPD] / 2, false); } }
HasteStatusEffect
using UnityEngine; using System.Collections;
public class HasteStatusEffect : StatusEffect { public const string HasteBeginNotification = "HasteStarted"; public const string HasteEndedNotification = "HasteEnded";
void OnEnable() { this.PostNotification(HasteBeginNotification); }
void OnDisable() { this.PostNotification(HasteEndedNotification); } }
However, the result is STILL the same. Even after I had specified that I only wanted the HasteStatusController script to only listen to notifications from the HasteStatusEffect script that is attached to the same game object that it is also attached to, it is still listening to notifications from the HasteStatusEffect scripts that are attached to other game objects on the field. This is concluded after observing how the units' SPD that were affected by Haste were multiplied by whatever number of units that were affected by it (i.e. if there were 2 units affected, each of the 2 unit's SPD stat would be multiplied by 4 times and so on).
|
|
|
Post by Admin on Feb 4, 2019 15:27:54 GMT
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class HasteController : MonoBehaviour { public GameObject target; StatusCondition condition;
private void Update() { if (Input.GetKeyUp(KeyCode.A)) { AddEffect(); } if (Input.GetKeyUp(KeyCode.R)) { RemoveEffect(); } }
void AddEffect() { condition = target.GetComponent<Status>().Add<HasteStatusEffect, StatusCondition>(); }
void RemoveEffect() { condition.Remove(); condition = null; }
private void OnEnable() { this.AddObserver(OnAdd, Status.AddedNotification); this.AddObserver(OnRemove, Status.RemovedNotification); }
private void OnDisable() { this.RemoveObserver(OnAdd, Status.AddedNotification); this.RemoveObserver(OnRemove, Status.RemovedNotification); }
void OnAdd(object sender, object args) { if (!(args is HasteStatusEffect)) return; var status = sender as Status; Debug.Log("Add:" + status.gameObject.name); }
void OnRemove(object sender, object args) { if (!(args is HasteStatusEffect)) return; var status = sender as Status; Debug.Log("Remove:" + status.gameObject.name); } }
|
|
|
Post by Admin on Feb 4, 2019 15:38:33 GMT
To answer your questions: 1. The haste status effect was removed from the unit, but the "Status" component (the sender of the notification) is still attached to the unit, so you can grab a reference to any other components on the unit as well. 2. The observer method of the notification is passed the "sender" as a parameter. You don't have to do anything special to look it up, but you do need to be able to know what it is, and cast it to the right kind of object.
Now, take a look at the code snippet I posted above. It might help to clear up a few things. I created a "controller" script and attached it to the "Battle Controller" game object - note it is not attached to any unit. When the scene loads, I manually assign a unit to the public target field that I exposed (this is just for testing purposes after all). Then I press the 'a' key to add a haste status effect - I can then inspect the units hierarchy if I want. Then I press the 'r' key to remove the status effect when I am ready.
I use the OnEnable and OnDisable to register and unregister from status notifications, but I do not specify a sender to observe, so that it listens to any status notification from any unit. That is how you would structure the real controller or system style pattern I had mentioned. In the observer methods, OnAdd and OnRemove, I first check the type of args to determine whether or not the notification refers to a type of HasteStatusEffect or not. If it doesn't, I abort early using the return statement. If it does, then I cast the sender of the notification (the status component) to a new variable of that type so that I can work with it and its GameObject hierarchy accordingly. In other words, you could grab a reference to the "Stats" component to raise or lower the speed stat at this point.
|
|
|
Post by wewechoo on Feb 6, 2019 14:28:15 GMT
Alright, I managed to finally get it to work properly after borrowing your code and modifying it a bit.
While I somewhat get what the code actually means, I feel like I actually need to go through over it once more in order to confirm that I'm correct.
The Haste Controller script is attached to the Battle Controller game object, and once activated, is set to listen to 2 notifications:
1. When a status effect is added.
2. When a status effect is removed.
When a status effect is added, it invokes the OnAdd function, which does two things:
1. Discern whether the status effect added is the Haste status effect.
2. Does whatever effects that comes with being inflicted with Haste.
This is basically the same for the OnRemove function, which does the second thing in reverse.
In addition, it does an additional thing in order to change and change back the stats correctly.
(As this is the part that I'm the most unsure about, I'll use an example to illustrate this).
If 3 units were afflicted by Haste, let's say Unit A/B/C, it assigns the thing that sent out the notification (i.e. the Status component) to a variable. So in this case, the Status components of Unit A, B and C will all be assigned to variables, and from there, we can traverse through the game object hierarchy to modify each of their stats. In this case there will not be any double-counting that takes place.
|
|
|
Post by Admin on Feb 6, 2019 17:32:03 GMT
I think you understand it all correctly, but to be sure I will add that if three units were given haste, that the controller would receive a separate notification for each of the three units. This means that the OnAdd method would be called three times, the first time from a status component attached to unit 'A', next by the status component attached to unit 'B' etc. The code in OnAdd will be the same and work regardless of which unit is being handled.
You could test this in the sample code snippet I gave you by assigning different units (with different names) to the target and running the test. The Debug Log will print the name of the unit that is targeted.
|
|
|
Post by wewechoo on Feb 7, 2019 3:41:53 GMT
Alright, thanks so much for helping!
|
|