Hello there,
After a year of using RPG Maker MV for my game I’m finally moving over to using Unity. So before learning the language, since I’ve done game programming for about 10 years off and on, I thought I would write out a kind of system for an in-game cutscene maker. Why a cutscene maker? Well, because my game is about 95% cutscenes with 5% qte action gameplay.
I needed some critique on a basic layout before I actually delve into implementing this into Unity. It basically uses RPG Maker’s system of creating cutscenes, as RPG Maker is basically just a cutscene creator anyway in my eyes.
So the first thing I’m thinking of doing is creating what rpg maker calls an ‘interpreter’, although I think it’s better called something like an ‘event manager’ because I’m not sure that that’s exactly what an interpreter is usually called in the programming world.
The point of having a main game interpreter is that one thing happens at a time in game, so that it’s not just control of manipulating space, but complete control of manipulating space and time, thusly having you able to make a cinematic and tell a story.
The idea is to create two caterpillar arrays:
Main Interpreter - This array or data structure holds all of the strings that will trigger the functions from the Unity api to make stuff actually happen in Unity.
Bin Interpreter - This array is Main’s ‘trash bin’, kind of. It collects each string/event that’s skimmed off of Main Interpreter. I don’t know if this will be totally necessary, but in an editing program this is like your Undo bin, so that you can hit Undo, which will push the last entry from this Bin back into the Main Interpreter.
I’m going to post two layouts. The trigger for the game is when a scene/map loads. The player object is placed within one of the scenes/map of the game.
Here’s what I’ve got so far. I’m mainly looking for critique from an experienced programmer for this outline:
On scene load:
Do: Set screen to loading image.
Check: Is Save Game Being Loaded?
If It Is:
Load Main Game Database from Save File into Main Game Database in game.
(includes Map data for every map in game)
Load Misc Database from Save File into Misc Database in game.
Load Main Interpreter from Save File into Main Interpreter in game.
Load Bin Interpreter from Save File into Bin Interpreter in game.
If It Isn't:
Using the Unity scene, pour events into Main Game Database. (this scene is starting for the first time)
Check: Debug mode?
Do: Place all object transform data based on data from Main Game Database
Check: Object trigger modes?
Do: Objects with Parallel Process gets it's own interpreter created with it's
events loaded into it.
Do: Objects with Autorun gets loaded into Main Game Interpreter.
Check: Are all objects placed?
Do: Wait 3 seconds for good measure, then...
Do: Add Event::FadeIn::Frames:: string into first entry in Main Game Interpreter.
Loop:
Do: Take first line from Main Game Interpreter.
Do: Cut the string into arguments for the appropriate function.
Check: Is this a proper script?
If It Is:
Do: Remove this entry from the Main Game Interpreter Database, next entry gets pushed to the front of the line.
Loop:
Do: Execute the appropriate function based on what the line said in the Interpreter. Stay in this loop
until the function returns an "end" or 0 or whatevers necessary to break this loop.
If It Isnt:
Do: Return an error message detailing what the string says like "Error in Main Game Interpreter at:".
The general idea is that the Main Game Interpreter takes the first entry from the top of it, cuts the string up into arguments and passes it to a function, then the Main Game Interpreter shrinks appropriately, throwing away the top string it just processed into the Bin Interpreter.
Here are the events that I’m going to implement into Unity to make this cutscene creator. These take directly from RPG Maker:
[Basics]
Wait::Seconds::
Event::FadeIn::Frames::
Event::FadeOut::Frames::
[Interpreter Commands]
InterpreterCreateLabel::LabelName::
InterpreterSkipTo::LabelName::
InterpreterRewindToLabel::LabelName::
InterpreterRewindByNumberofEvents::NumberofEvents::
[Save/Load] ***** Important to tackle this first and foremost
Event::SaveGame::
Event::LoadGame::
[SFX]
Event::PlaySE::Name::
Event::StopSE::Channel::
Event::PlaySEEx::Name::Channel::Volume::Loop?::Wait::@ Obj,WaypointIDorName::
Event::PlayBGM::Name::Volume::Loop?::
Event::BGMFadeOut::Frames::
Event::BGMFadeIn::Frames::
Event::StopBGM::
[Pictures]
Event::PictureShow::Name::PicNumber::X::Y::Opacity::
Event::PitureShowEx::Name::PicNumber::X::Y::FadeIn?::Frames::Opacity::
Event::PictureMove::PicNumber::X::Y::Opacity::
Event::PictureErase::PicNumber::
Event::PitureFadeIn::PicNumber::Frames::
Event::PictureFadeOut::PicNumber::Frames::
[Screen FX]
Event::ShakeScreen::Intensity::Frames::
Event::FlashScreen::Intensity::Frames::
Event::Weather::Type::Intensity::
Event::TintScreen::Type::Intensity::
[Objects]
Event::CreateObj::ObjName:: ***** "Player" cannot be created, and has to throw back an error 'Player cannot be created as a new object. Player is the primary game object already!'
Event::smile:eleteObj::ObjName:: ***** "Player" cannot be deleted, and has to throw back an error 'Player object cannot be deleted! It must remain invincible!'
Event::smile:eleteThisObj::
[Object Events]
[Movement Events]
Obj::ObjName::Wait::Frames::
Obj::ObjName::WalkRunSpeed::Speed::
Obj::ObjName::MoveTo::Obj,WaypointIDorName::Wait?::
Obj::ObjName::RunAwayFrom::Obj,WaypointIDorName::Wait?::FramesIfWait::
Obj::ObjName::TurnToward::Obj,WaypointIDorName::Wait?::
Obj::ObjName::TurnAwayFrom::Obj,WaypointIDorName::Wait?::
Obj::ObjName::Turn90r::Wait?::
Obj::ObjName::Turn90l::Wait?::
Obj::ObjName::SteppingAniToggle::OnOrOff::
Obj::ObjName::smile:irectionFixToggle::OnOrOff::
Obj::ObjName::InstantMoveXYZ::X::Y::Z::
Obj::ObjName::InstantMoveTo::Obj,WaypointIDorName::
[Acrobatics]
Obj::ObjName::Jump::Speed::Wait?::
[Graphic Events]
Obj::ObjName::SetOpacity::OpacityNumber::Frames::
Obj::ObjName::ChangeGraphic::CharSetName::IndexNum::
[Camera]
Event::CameraMove::X::Y::Z::Frames::
Event::CameraMoveTo::Xpos::Ypos::Zpos::Frames::
Event::CameraFollow::Obj,WaypointIDorName::FollowDelay::
Event::CameraRotate::Xr::Yr::Zr::Frames::
Event::CameraMoveRe::Obj,WaypointIDorName::
Event::CameraFocusToward::Obj,WaypointIDorName::
Event::CameraFaceShot::Obj,WaypointIDorName::Frames::
Event::CameraCloseUpFaceShot::Obj,WaypointIDorName::Frames::
Event::CameraZoom::smile:istance::Wait::
[Game]
Event::HUDshow::
Event::HUDhide::
Event::GameOver::
Event::Title::
Event::TimerSet::Seconds::
Event::TimerShow::
Event::TimerHide::
[Animations]
Event::ShowAnimation::AniSetName::
Event::HideAnimation::AniSetName::
[Text]
[Standard Top, Mid, Bot Text Box]
Tp::position::
T::Text Goes Here::
[Standard Choice Box]
Tcb::Ch1::Ch2::Ch3::Ch4::Ch5::Cancellable?
[Text Box]
TBp::X::Y::
TBT::Text Goes Here::
[Choice Box]
TBcb::X::Y::Ch1::Ch2::Ch3::Ch4::Ch5::Cancellable?
Tfont::Font Name::
Tsize::Text Size::
VA::SFXFileName::
[Text Codes]
\| - Wait 1 second
\. - Wait 1/4 seconds
\{ - text size up one
\} - text size down one
\^ - don't wait for input after displaying text
\> - display remaining text on line all at once
$variable - display a variable with name of 'variable'. Requires space after it.
[Movies]
Event::MoviePlay::Name::Skippable?::
So the idea is that these events trigger functions from the api like this:
Check, If: Wait::Frames::
I think it'd be like: WaitForSecondsRealtime(MathForFrames(InsteadOfSeconds));