NodeScript - Scripting for Level Design

Hi all! I’ve been working on a tool for Unity for a bit now. It’s called NodeScript, and it’s intended to make scripting for level design easier.

I’ve worked on a number of Unity projects at this point, and I kept running into the problem of wanting to hook up really simple triggers, behaviors, and interactions in a scene, but they were so specific to the level that it was ridiculous to write a whole script file for them. I would end up cluttering my Assets directory with stuff like BrokenRotatingPlatform.cs, ShopkeeperWaveAndBellOnEnter.cs, and BrokenBarrelCounter.cs. It always bothered me that I was writing code to do scene and level-specific stuff. It was also always fussy to set up (lots of dragging of specific objects into reference slots), especially in the case where I would end up writing these elaborate choreography scripts… Basically, setting up things that were quick and easy in older engines would always turn into a “thing” in Unity.

There are other things out there on the Asset Store, like PlayMaker, that address some of these problems, but they’re really full replacements for programming, which isn’t really what I wanted. I just wanted something like good ol’ Hammer had, only less jankey. What I wanted was something that would let level designers put in little hand-crafted interactive details, something that let me build up the character of the world. It needed to be fast to work with, saved in the scene file, flexible but not overly complex, and clear about the spatial connections that these scripts often have. I wanted something that was focused on being a helpful tool, but wasn’t so complicated that users could get themselves into real trouble. NodeScript is what I’m making towards that end.

I’ve got it functional at this point, and so far it does a pretty good job at quickly letting you do things like:

  • Start with the scene black, wait until a sound is done playing, and then turning on player control and fading in
  • Automatic doors when a character enters a trigger
  • Changing properties of a material on a timer to make a light blink
  • Play a door unlock animation when the player has dropped objects on several buttons
  • Parent an object to another on collision
  • Playing a sound on cue, and then firing a particle system once the sound is done playing

I’m posting this here because I was hoping to get some feedback into what other people would want out of something like this. Is there any level scripting you’re working on right now that’s more of a pain in the butt than it should be? What are the sorts of things you would want to do with something like this? Let me know so I can make them happen!

TL;DR: NodeScript is about level scripting. Quick and easy, stored in the scene, spatially oriented. Tell me how to make it better!

Here are some screenshots of what it looks like right now. It’s still pretty rough, and I do intend to visually polish it up, but I also want to keep the focus on utility over aesthetics.

I’ll be posting with more progress as time goes on, as well as questions. Hope to hear from you all!

I’ve gone and implemented my own version of Gizmos via Graphics.DrawMeshNow, which seems to be working pretty well so far. Right now it looks pretty much the same as normal Gizmos…

But it also lets you do stuff like this:

Gizmos with custom meshes! Hats for everyone!

I’m also working on prettier node connections:

It would be nice if I could use Handles.DrawBezier, but it doesn’t seem to be depth tested. Once I’ve finished my own wire bezier connections, I’m going to return to adding more nodes. Now that I’ve opened up the possibilities of what I can make the system look like, I need to figure out what it SHOULD look like…

I spend the last few weeks plugging away at filling out node types between other projects. Here’s a list of what I have in so far:

General nodes (these wait to be triggered and then do something):

  • Audio Fade - fades a target Audio Source to a target volume level
  • Audio - basic controls for a target Audio Source; Play, Pause, Stop, etc
  • Debug Log - outputs a string to the debug console
  • GUI Fade - fades in or out a fullscreen OnGUI texture
  • GUI Overlay - controls an OnGUI texture in screen coordinates
  • Load Level - calls Application.LoadLevel on the specified level
  • Particle System - target Particle System controls, Play, Stop, Clear, Emit, etc…
  • Physics Impulse - applies a physics impulse to a target Rigidbody on trigger
  • Rotate - rotates a target Transform in a number of ways, from spinning to opening door-style
  • Translate - moves a target Transform between points, good for sliding doors and other things
  • Set Active - sets a target GameObject as active or inactive
  • Set Animation - sets target Animator triggers, floats, ints, etc
  • Set Material - sets a target Renderer’s material
  • Set Material Property - sets a Material’s properties, local or shared
  • Set Parent - sets a Transform’s parent. duh
  • Set Position - sets a Transform’s position, globally or locally
  • Set Rotation - same, but with rotation
  • Set Scale - same again, but with scale!

Trigger nodes (these wait for a condition to be met and then send out triggers):

  • On Start - triggers on Start()
  • On Collider Collision - triggers separate outputs on OnCollisionEnter, OnCollisionStay, and OnCollisionExit
  • On Collider Trigger - same, but with triggers
  • On Raycast - triggers when the raycast hits a specified (or any) object
  • On Input - triggers when the user presses a specified key, mouse button, controller button, or virtual input

Variable nodes (these hold general variables that can be set by other nodes or set the values of other nodes):

  • Bool
  • Int
  • Float
  • Vector
  • Color

Logic nodes (these do special NodeScript logic things):

  • Counter - can be incremented and decremented, and then triggers on certain values or ranges
  • Delay - wait a specified time, and then triggers, super great for easy choreography
  • Trigger Group - takes in one trigger and splits it out to a bunch of other nodes

This is a good set of nodes to start with, and I’ve been using them to hook stuff up for other projects. There need to be more, obviously, especially in the logic category.

What do you all think is missing from this list? Anything you would want to do? Things you’ve used in other engines that are super awesome?

Here’s a picture :slight_smile:

1942880--125617--2015_01_30_Inspector.png

The past couple weeks I was working on another project. Fortunately, I ended up using NodeScript there, and came away with a list of needed functionality and usability fixes. It’s always good to get time away from a project like that, it can give you perspective and fight burnout.

I got bezier connections in and working, which required a few different passes on figuring out the best way to wrap connections backwards. It makes for a much cleaner and easier to follow look.

I also got some new editor functionality in, like connection highlighting, intelligent picking, and right-clicking to disconnect. When working with NodeScript in the other project, I also discovered that the Frame Selection functionality acted pretty dumb most of the time, since it had no idea the size a node’s bounds. Without some way to override the bounds, I ended up overriding the F key to zoom into an intelligent level when a Node is selected.

Next up, I’m going to be doing some internals cleanup and testing. I’ve only tested NodeScript with C# so far, and although it should work with JS in theory… Well, I’ll be testing that soon.

Does this only work in the editor?
Any way this could be made to work with standalone to create user levels and triggers?

Right now it’s an editor-focused tool, but each node is just a script attached to a GameObject. It would be totally possible to let players create their own scripts with this, but it would require re-writing the interface, as right now it’s piggybacking on a lot of Unity Editor stuff (Gizmos, Inspectors, etc).

If there’s interest, I can look into this at some point!