Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

1,468 Excellent


About Rick

  • Rank
    Advanced Member
  • Birthday 12/04/1979

Profile Information

  • Gender
  • Interests
    Family, golf, football, programming, games

Recent Profile Visitors

54,927 profile views
  1. Tessellation should really help to add detail to our games! It seems like I don't see a lot of tessellation in games that I play these days. I wonder why that is because if I recall the tech has been around for 3-5 years already?
  2. The bots are having conversations with each other! After the human race is all dead bots will still be replying to each other on forums and the aliens that find earth will be very confused.
  3. So in the scene graph you have a camera object as a child of your player pivot? If that's the case then from your script that is attached to your player pivot you'd do something like this in the Start() function: self.camera = self.entity:GetChild(0) This assumes you only have 1 child to your player pivot and it's the camera. If you have more than one child I think you can use self.entity:FindChild("camera_name_here") Scripts don't automatically get variables like you're thinking because they are children or parents of things, but there are ways to get them with GetChild(), FindChild(), GetParent() calls. This isn't 100% ideal though. Ideally you'd create a script parameter and drag and drop the camera in the scene graph to that parameter. To do this at the top of this script add: Script.camera = nil --entity Then when you select your player entity in the scene graph you'll see the camera parameter show up. Drag and drop the camera to this slot and now you've made a link between the camera entity and this script camera variable. Now you can use self.camera in your script. You can do this with any entity btw.
  4. If this is your entire script then you can't just do self.camera like that. As the error is saying self.camera is nil. Just curious as to your thinking on why you think it would work as it can help explain why it doesn't better.
  5. Close. You don't load cameras separately, just the models really. So let's say you have 10 different models in your game. In a loop just for clarity: LoadModel1 Update, Progress bar to 10% LoadModel2 Update Progress bar to 20% *repeat until you loaded all models Load Map (this will be fast now because you already loaded the models and when this goes to load those models it'll use the instances in memory vs going to disk). Note that you wouldn't manually set the % like this. You'd want to figure out how many models you need to load per map and calculate the % as you're looping over them all. Note this is a "hack" though. We shouldn't have to do something like this and hopefully Turbo handles this better.
  6. Yue, what gamecreator is saying is that the biggest time to load an entire map is loading all the models that are in the map. The LE map doesn't actually have the mdl files inside it. The map file just has information about what mdl files to load (mostly). In LE if a model is already loaded the next load call on it will just be creating another instance of the model (this means it doesn't have to go to disk to do this. it just looks at the already loaded model in memory and copies it.). Creating instances are fast. So if BEFORE you load your map you manually call load on all the mdl files you need then calling the map load will be faster. Since you're manually calling the mdl files to load you can loop over that process and make the progress bar, then at the end call your map load. Yes, there will be a slightly below still when you load the map but it'll be MUCH smaller and probably not noticeable by the user. So it sort of simulates map loading progress bar. This does have the side effect of needing to manually know which models to load for each map. Ideally one wouldn't load every model in the game if it's not used in a map. This is really why the map file should just be json so we can easily open and manipulate it ourselves. Even add fields to it.
  7. The loading bar idea should be noted for the new engine. Make the map format json or something so the information about what should be loaded can be loaded first then it's easy to see how many models there are and then the engine could expose a callback after each resource is loaded from the map and let a full iteration of the engine happen after each one so we can display our own progress bar.
  8. Rick

    Coroutine Sequences

    You are starting to get into the idea of behavior trees a little there (which you should totally implement as well into Turbo as they are amazing for AI). I did implement a general behavior tree with Lua. I found a lua implementation and converted it to work with LE. I implemented that into that dinosaur game me, Tim, and Shad did (which I can't find in the games section for some reason). https://github.com/tanema/behaviourtree.lua If you start reading up on behavior trees you see they have the idea of sequences. So the actual task or doing is the thing you originally were talking about with coroutines, but the structuring of all these tasks is what the behavior tree handles. A nice UI to manage the trees is handy as well. I think I used this https://github.com/behavior3/behavior3editor which exported to json and then the library I modified I created a function that loaded the json result of this editor into the behavior tree structure. It was pretty slick actually. Behavior trees have the idea of interrupts that you can put on any branch that would look for things that should take the AI off the current task and rerun the entire behavior tree again. When behavior trees are being ran through they run through your sequences in order so you always put the highest priority sequence first like getting shot at, or starving. Some sort of self preservation. When you're in a lower priority sequence the interrupt would say check your hunger level and if < 10 it would bail out of the current sequence and rerun the tree, which then the highest priority sequence would see you're hunger and then run it's sub sequences like find food, or cook food, whatever. You can play around with the editor online: https://www.behaviortrees.com/#/editor So if you hover over the Nodes header section on the right a New link comes up and that's where you'd make your new node actions like WalkToPoint or condition like IsHungry. It's actually really cool, very powerful, and fun to play with! You can even dynamically expand an actors "knowledge" by adding entire behavior trees as sub sequences! Imagine you creates a behavior tree that just has the sequence of "How to start a fire when cold". Then let's say you have 5 AI around your map. You start them with a basic behavior tree that has sequences like Find Food, Hunt, etc but you give 1 of them the "How to start a fire when cold" sequence. Then you code the game that when 2 actors bump into each other they share sequences in their behavior tree they have so you then give the other actor the "How to start a fire when cold" sequence and now you have AI teaching each other sequences they know. One might be able to expand this to make a more "real" AI that tries to randomly mix and match actions (you'd just have to code a bunch of actions that are available) to create their own sequences and if those sequences help their stats (hunger, thirst, etc) in any way they keep them and if they don't help they remove them! How cool would that be!
  9. Rick

    Coroutine Sequences

    Yes with coroutines. These things are amazingly powerful. So I'd say while this does work for some situations it's not as flexible. Sometimes you want to run multiple coroutine enabled functions at the same time and not continue until both are done. In a cut scene let's say you want to move from point A to B but also kick off some audio (the bad guy is talking as he's moving). He will reach his destination point before his speech is finished. The next step is to move again, but you want his speech and his first movement to be completed before you continue on. In my cut scene library I had my coroutine enabled methods return ID's of the coroutine itself, then made a method that would check if that coroutine was completed or not. So I could start both coroutine enabled functions and then do a loop checking if both were in a 'dead' state before continuing. local moveId = MoveToPoint(...) local speechId = StartAudio(...) -- don't recall lua syntax for looping atm while(IsCompleted(moveId) == false && IsCompleted(speechId) == false) loop -- continue with something else I would think at a minimum what you could do is make each script function a coroutine, or maybe let us somehow define that a script function should be coroutine enabled. This is what I did in my state manager library. In the scripts Update() I call my state manager Update() function. You change states by just calling stateMgr:ChanageState("StateName"). You added the script 'self' when creating the state manager because when you changed states it would look for functions of that state in that script by concatenating the state name to _Enter(), _Exit(), or _Update() and since you can search for functions by string name in Lua if the StateName_Enter() or StateName_Exit() function existed it would make a coroutine from them. The Update() was a normal function that looped while in that state, but I found myself using _Enter() more because coroutines rock. It might be nice to just have state type stuff built into these LE scripts honestly. States usually have an enter, exit, update. You don't need an update as you can get the same behavior by looping in enter and yielding out though. Exit is nice in case there are any cleanup stuff for that state. Wherever you are in that script you can change the state by calling some kind of ChangeState() function. Since you're dealing with coroutines you sort of need that because it tells the underlying system to stop calling that coroutine. If you're curious on how this works I have the library uploaded to the workshop. It's FSM (Finite State Machine). I think it's easy to use and gets the point across with states that have their enter/exit functions coroutine enabled.
  10. Rick

    Coroutine Example

    "The program will just silently close with no error message." Look at the definition of coroutine.resume() because it returns 2 values and 1 of them is if there is an error. I noticed the debugger doesn't show these so if there is an error I write it out to console so at least I can see the error.
  11. I think user events are very useful in this kind of subscribe/publish style because it allows for other scripts to know about whatever gameplay event you want without the script needing a reference to another script or entity. Cross script communication via events in my view is the best way to communicate. Allow the EmitEvent() to take a second parameter which is the value that will be passed to the subscribed functions. Since it's lua you only need 1 parameter and it can be a table that the person emitting the event fills out and if you are catching an event you have to just know the structure of said event parameter (a reasonable request). This would make using 3rd party scripts that emit events easier I think. Let's think about when we create enemy instances on the fly (not via the editor) and we need them to know about certain things the player is doing. How do we do that today? The enemy script either needs to get a hold of an instance of the player or the player get a hold of instances of the enemies so they can communicate. How they do that isn't very efficient or wise because it either means you're storing a global variable of the player so the enemies can get it (globals bad and error prone) or the player script is looping over every enemy to get a reference of them but enemies could be loading all the time so this doesn't work well. With the event system you can screw all that noise and just have the enemy script bind to a certain event that the player will emit. This way neither need a reference to each other to talk. So in summary user events gives us a way to have cross script communication without needing references of scripts/entities. I agree with this. Events work well for cross script communication and UI stuff, but gameplay stuff like picking objects work best with these inline procedural functions. Both are needed.
  12. The way you bind those events, in my opinion, is how the GUI events should work as well. self.btnExit:BindEvent(ON_CLICK, self, self.btnExit_OnClick) or self.btnExit.onClick:Bind(self, self.btnExit) Normally you have to pass the script itself as well so you can pass it as the first parameter tot he function so we can define it like function Script:btnExit_OnClick() end and use self inside of the function to refer to the script itself as 'self' is hidden 1st parameter to the function
  13. I will say good job at moving the core logic part out of PostRender
  • Create New...