Search Unity

Handling story?

Discussion in 'Scripting' started by hexiy, Oct 23, 2017.

  1. hexiy

    hexiy

    Joined:
    Mar 17, 2016
    Posts:
    5
    Hey, so i think i'm missing something i should not be missing. Currently i have game with different story lines, there will be max 10, but i don't want to be running 10 coroutines having WaitUntil in them every frame, so i'm looking for "something" to be called, when another function is called, for example, i'd have some sort of story manager to push me through "steps" of story once particular functions are fired, BUT i don't want to have things like "bool doorOpened" in those functions, i want to be able to do something like, "someMagicalStuffImMissing".ListenForThisFunctionCalled(DoorOpened). Thanks
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    concept:

    Have a story manager that is simply a listener:

    Code (csharp):
    1. public class StoryManager{
    2.     public Dictionary<string, Story> stories;
    3.    
    4.     public StoryManager(){
    5.         stories = new Dictionary<string, Story>();
    6.     }
    7.    
    8.     public static Story AddStory(string name, Story story){
    9.         if(stories.ContainsKey(name)){
    10.             Debug.Log("Story is already active: " + name);
    11.             return stories[name];
    12.         }
    13.        
    14.         stories[name] = story;
    15.         return story;
    16.     }
    17.    
    18.     public static Story GetStory(string name){
    19.         if(stories.ContainsKey(name)){
    20.             return stories[name];
    21.         }
    22.         return null;
    23.     }
    24.    
    25.     public static bool CanAvance(string name, int to){
    26.         if(stories.ContainsKey(name)){
    27.             return stories[name].CanAvance(to);
    28.         }
    29.         return false;
    30.     }
    31.    
    32.     public static bool IsStoryFinished(string name){
    33.         if(stories.ContainsKey(name)){
    34.             return stories[name].IsFinished();
    35.         }
    36.         return false;
    37.     }
    38.    
    39.     public static int AdvanceStory(string name, int to = 0){
    40.         if(stories.ContainsKey(name)){
    41.             return stories[name].Advance(to);
    42.         }
    43.         return false;
    44.     }
    45. }
    46.  
    47. public class Story{
    48.     public string Name {get;set;}
    49.     public int Index {get;set;}
    50.     public int Max {get;set;}
    51.    
    52.     public bool CanAvance(int to){
    53.         return to <= Index + 1;
    54.     }
    55.    
    56.     public bool IsFinished(){
    57.         return Index == Max;
    58.     }
    59.    
    60.     public int Advance(int to = 0){
    61.         if(to == 0){
    62.             to = Index + 1;
    63.         }
    64.         if(to > Max) {
    65.             to == max;
    66.         }
    67.         Index = to;
    68.         return index;
    69.     }
    70. }
    So the usage would be something like:
    Code (csharp):
    1. OnCollisionEnter(other col){
    2.     if(col.tagName == "Player") {
    3.         var story = StoryManger.GetStory("Bob's Great Door Opener Story");
    4.         if(story != null){
    5.             if(story.CanAvance(3)){
    6.                 story.Advance();
    7.                 // do code to open door;
    8.                 }
    9.         } else {
    10.             Debug.Log("You can't do that yet");
    11.         }
    12.     }
    13. }

    (of course, all this is without testing and is kind of paraphrased)
     
    Last edited: Oct 23, 2017
  3. hexiy

    hexiy

    Joined:
    Mar 17, 2016
    Posts:
    5
    Yeah, but i thought if there isn't some way to listen to function being called, so i wouldn't actually have
    Code (CSharp):
    1.  var story = StoryManger.GetStory("Bob's Great Door Opener Story");
    2.         if(story != null){
    3.             story.Advance();
    in OnCollisionEnter
    but i'd have something like OnBobsGreatDoorOpenerStoryDoorOpened() in my Story1.cs-which would be called, whenever OnCollisionEnter would be, because if you have more stories it could get messy with all the checkings in functions, here OnCollisionEnter, like, if i'd want to make it to wait for not Collision but trigger, one way is to just paste the code to OnTrigger function, but in my Story1.cs i'd like to just say, "SomeMagicStuffIDon'tKnowAbout".AdvanceIfPossible((3-that's something like progress index, with every completed action this would increment),House.GetInstance().door.OnTriggerEnter). So basically just wanted to know if there is a way to have one function-OnCollisionEnter invoke other-ProgressStory without having to write anything in the OnCollisionEnter-to make it really scalable? Of course OnCollisionEnter wouldn't work here because i need to know if it collided with player...
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Abstract the details away from the implementation. Make a generic MonoBehaviour that takes the name of the story to get as an Inspector value. Then use that value in OnCollisionEnter.
     
  5. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Given the scope of what you are talking, you would need access to something like:

    Physics.onCollisionEnter

    Which of course does not exist. If it did then you would have a good case for making a truely scalable system, but only to a degree. You would still have to put on each object that would advance the story as you needed. So ultimately, you would still be stuck writing code on each object that you want to have this ability on.

    Another idea is to do all of this from the standpoint of the player. So every event or thing that he does makes a call to a log and query system, then you simply watch the log for events.

    i.e. Player walks up to a door, presses his use button, the use button sees the door as his target. the use function then asks the door if it has a story (say, you can't open this door unless you are level 10, or you have a blue key) If it does not have a story, it then asks the query system if it can find a story that mentions the door. If so, it comes back and asks if the player is on that story, and if the player has reached the necessary point on that story to open the door. Now, basically two events happen, either he is on the story and has the necessary ability to open the door, or there is no story. The door will open. If not, then the door will not open.

    The global query system with the ability to look up if any of the key points of the story have a certain named object would be your global scalable system, not the physics system. Not to say that then, you could not write triggers and such that will query that system.