[GUIDE]How to make mods for MySummerCar?

NOTE: This is a work in progress please let me know if anything is wrong, something feels like its missing or you have any questions.
NOTE: Some of the code/snippets have been written on the fly and has not been tested. Some may be faulty but please notify if they are and I will correct it!
NOTE: If you have any questions, need help or perhaps are thinking about something NOT covered in this thread PLEASE POST YOUR "OFF TOPIC" QUESTION IN THIS THREAD:
http://www.racedepartment.com/threads/how-too-start-programming-mods-for-my-summer-car.146394/

Skip to actual guide!
Scoll down to the headline "So where should I start?" and begin there!

What will I cover?
I will cover where to start in order to start making mods.
I will provide some very helpful snippets of code.
I will provide useful links and a FAQ.

Why are you doing this?
When I got introduced to the game and my friend showed me the mods I thought it would be fun trying to make one myself but that was not as easy as I thought.
(I NEVER inteded to ever release the mod I created either... but it became too good lol)
With a bit if research I managed to find MSCLoader Wiki and that got me started and setup.
Once everything was setup and working I started by creating a mod-project using the template provided by @piotrulos (The creator of the MSCLoader and forever a legend) and here is where I ended up stuck.
If I wanted to make some changes to an object in the game... How would I proceed?
If I wanted to make some changes to information in-game... How would I proceed?
This is where I ended up researching further and how I ended up finding the new thread created just 30 minutes earlier.
This thread is where I ended up being active in for a while when I was getting around and learning the process of making mods. (This is my first time ever...)
You can find this thread here: http://www.racedepartment.com/threads/how-too-start-programming-mods-for-my-summer-car.146394/

... and this is why I'm creating this guide, simple as that :)

(This part bellow is optional)
My initial instinct was to create a plugin that would make a list of all gameobjects in the current scene (World)... that way I knew what I could work with..
MySummerCar SceneObjects SourceCode: https://pastebin.com/pVqttvzH
MySummerCar Scene Objects list: https://pastebin.com/tkXq5mYd (Version: Dec 2017, this has changed!)

This was however, very, unnecessary since @zamp has created, litteraly, the ultimate developer toolkit for modding!

Also, after this I started PM conversations with @kunedo who has been very helpful with Ideas... hes just a really friendly and amazing guy all around helping etc. Thanks, really!

So where should I start?
First
, you will need an IDE; Visual Studio.
You can find it here: https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15

Secondly, you should start with finding the MSCLoader Wiki and start setting up your environment. Read through and learn how to use the MSCLoader:
You can find MSCLoader Wiki here:
https://github.com/piotrulos/MSCModLoader/wiki

NOTE: You may download either x86 or x64 bit version of Unity and reading both for player and developer is very useful.

Third, start by downloading and "installing" the "Developer Toolkit" so you can easily find and quickly modify gameobjects in the world.
Saves a lot of time not having to make changes, build and restart the game every time you try a new set of code for example in placing or re-placing gameobject in the world.
You can find Developer Toolkit here:
http://www.racedepartment.com/downloads/plugin-developer-toolkit.17214/

NOTE: Some Objects/Components also needs referenses to Assembly-CSharp.dll file.
("Steam\steamapps\common\My Summer Car\mysummercar_Data\Managed\Assembly-CSharp.dll")
Drivetrain, for example, does need this reference to work properly.
Thanks to @tommojphillips for finding this!

How can I make changes in-game?
This is fairly easy and basic kowledge. MySummerCar is created using Unity® software and that opens up a whole lot of methods, classes and libraries we can use.
Transforms, for example, is used to store an objects position, rotation, scale and parenting state.
MySummerCar is also using an asset called PlayMaker which makes it a whole lot harder at the same time. Depending on your goal ofcourse.

First, if you would like to make changes to example the car, Satsuma for example...
We need to create a variable/reference name:
Code:
GameObject satsuma; // Making a variable
Right now the reference is empty and we need to give it a reference to the object in the game..
Give it a reference/value:
Code:
satsuma = GameObject.Find("SATSUMA(557kg, 248)"); // Giving our variable a reference/value
Now the reference is set and we can access for example the transforms of the object to move or make changes. We can also activate/deactivate the object in the world. Now that we know how to access an object... How can I make changes to the information in the game?
This part is a bit tricky.. You need to find out which GameObject in the scene is "hosting" the component which makes these changes in order to change them... Unless they are maintained by a singleton instance. If they are maintained by singleton and are instanced they can, globally, be read or changed without the need of the "hosting" object.

Making changes to a component/variable:
Code:
satsumaDriveTrain = GameObject.Find("SATSUMA(557kg, 248)").GetComponent<Drivetrain>();
This means that you are getting the component "DriveTrain" on the Object "SATSUMA(557kg, 248)" and you may make changes or read values/variables from that component.

If it is a singleton variable or information you are looking for you may use a foreach method to get what you want to find:
Making a foreach for PlayMaker FSM:
Code:
// FloatVariables can be BoolVariables, StringVariables, GameObjectVariables, ObjectVariables, MaterialVariables and IntVariables
foreach (var flt in PlayMakerGlobals.Instance.Variables.FloatVariables)
{
    switch (flt.Name)
    {
        case "PlayerCurrentVehicle": // This is not a float
            _carCurrent = flt.Value.ToString();
            break;
        case "PlayerFatigue":
            _fatigue = flt;
            break;
        case "PlayerThirst":
            _thirst = flt;
            break;
        case "PlayerHunger":
            _hunger = flt;
            break;
        case "PlayerStress":
            _stress = flt;
            break;
    }
}

How do I detect if a player is in vehicle/car/"drive mode"?
Taking a look back to our code earlier we can use the PlayMaker FSM here and check if player is in any vehicle.
Code:
if (FsmVariables.GlobalVariables.FindFsmString("PlayerCurrentVehicle").Value != "")
{
    //Player is in drive mode
}

How do I use custom assets?
Code:
//Define objects
AssetBundle assets;
GameObject turbo;

//Onload.. We load, initialize and give references.
assets = LoadAssets.LoadBundle(this, "turbo.unity3d"); // Load this asset
turbo = assets.LoadAsset("turbo_prefab.prefab") as GameObject; //get specific prefab
assets.Unload(false); //Unload once all prefabs has been gathered to clean memory

//Placement
turbo = GameObject.Instantiate(turbo); //Instantiate object in the world
// OPTIONAL: turbo.transform.SetParent(GameObject.Find("satsu").transform, false); // We can set it as child object

//We set pos, rot & scale | Be aware, there are localPosition and Position. Choose relative to the use.
turbo.transform.localPosition = new Vector3(0.3f, 0.16f, 1.02f);
turbo.transform.localRotation = Quaternion.Euler(0f, 0f, 0f);
turbo.transform.localScale = new Vector3(0.0005f, 0.0005f, 0.0005f);

(I cant find the player!)
How do I find player?
@piotrulos stated in an early comment/reply that:
In 0.4 OnLoad will be called after game is fully loaded.
When OnLoad is called you can simply use this code:
Code:
GameObject player = GameObject.Find("PLAYER"); // Simple as this

OLD TUTORIAL; MSCLoader <= 0.3.5;
Finding the player is a bit tricky compared to finding another object in the world since it is "spawing" rather late.
Once OnLoad has finished running in your mod it has most likely not spawned yet and will result in a nullreference exception.
How do we make this work?
There are multiple options but I'm going to show you two:
Code:
//First option is the Coroutine method:

void Something()
{
   //Start coroutine
  StartCoroutine(setup());
}

IEnumerator setup()
{
   yield return new WaitForSeconds(15f); // Wait for something 15 sec
   ModConsole.Print("Success!");
}

Code:
//Second option is the update method:

public override void Update()
{
    //Loops untill player has spawned. May cause some lagg...
    if((GameObject)player == null)
        player = GameObject.Find("PLAYER");

    //Wrap other codes inside this container
    if(player != null)
    {
    //Run mod...
    }
}

**Threading removed**

Good luck and have fun!

Annoyances (and tips) of building mods:

When you are making mods you'll be, eventually, annoyed by three (major) things...
1: As a developer you need to manually copy the mod to the mod folder every time you makes changes/build the mod.
But that can be fixed by using this piece of code:
Code:
copy /Y "$(TargetDir)$(TargetName).dll" "C:\Users\YOURUSERNAME\Documents\MySummerCar\Mods"
It's basicly a "batch"/CMD command to copy the mod dll file to the location of your MSC mod folder.
How do I do that?
aaf95f2caf42619f48dcaefb508a5bb6.png

A: Right-click -> Properties
B: Find the tab "Build Events"
C: Find "Post-Build Event Command line" textarea and modify/copy the code above for everything you want to move with the build on each seperate lines.
D: Save.
E: Build and Enjoy!

2: You will need to restart the game a lot in order to test out the mod and check it out. (There, currently, isn't a way around this atm)
3: Bad reviews.
You may get bad reviews from users who doesn't "install" the mod correct, haven't bought the actual game and is playing on pirate copies etc.
My advice.. Brush it off and don't bother. If you enjoy creating, create and if you get a bad review or someone is being mean, ignore them and continue with your work.

My experiences and mods:
My experience has been great, No dubt. BUT lately i must admit that my interests have turned and I have been forced to focus on diffrent things. Work as an example has been very hectic.
I caught a break now and I wanted to help out the community :)

MySummerMultiMod: http://www.racedepartment.com/downloads/mysummermultimod.19405/

Useful links:
MSCLoader Wiki : https://github.com/piotrulos/MSCModLoader/wiki
PlayMakerFSM : All PlayMaker FSM
@zamp : https://github.com/zamp/MSC-Mods
@Roman266 : https://github.com/GishaSeven/Plugins-for-MSC-ModLoader
@tommojphillips : 2 Links below.
ModAPI: https://github.com/tommojphillips/ModAPI/wiki
Demo: https://github.com/tommojphillips/AttachObjectDemo

Special thanks to everyone who has provided information or helped with some outdated information!

Good nite everyone :sleep:
 
Last edited:
Good tutorial

As for Threading OnLoad it won't be needed when 0.4 will be released.
In 0.4 OnLoad will be called after game is fully loaded
Also in 0.4 will be real-time debugging

That sounds amazing!
It will sure clean up a lot of code, looking forward :)

I've made it "Sticky" for now.
Thank you!
Hopefully this clears up a lot of things for the newer modders :)
 
Double post sorry, but after second glance I noticed the loading in separate thread. If I remember correctly, Unity API isn't thread safe so it's ill advised calling unity functions from separate threads. It's why they don't allow to call Unity API from other threads when you create scripts in their editor. Worst case scenario is currupting variables and saving them which would lead to currupt save game files.
 
Double post sorry, but after second glance I noticed the loading in separate thread. If I remember correctly, Unity API isn't thread safe so it's ill advised calling unity functions from separate threads. It's why they don't allow to call Unity API from other threads when you create scripts in their editor. Worst case scenario is currupting variables and saving them which would lead to currupt save game files.
Sorry @wolf_vx, I have totaly (dont know how) missed your reply!:cautious:
You are correct about multithreading!
Unity3D's methods are mostly mono-thread and not thread-safe. However any 'static' field you make will be thread-safe after you use some of your System.Threading skills.
With this being said, using a static field as a wrapper for a Unity3D method may yield... unexpected results.
But basicly the only thing you can't do is use Unity API methods themselves across different threads, as they are not thread-safe

Although, you could, theoretically, pass variable information back to main thread using Deligates from a thread.
This is my understanding of the situation and please correct me if Im wrong as this is important! :thumbsup:


I'm looking forward to having a look as soon as possible but It'll have to be another week Im afraid.
Updating thread as soon as I can! :)
 
Sorry @wolf_vx, I have totaly (dont know how) missed your reply!:cautious:
You are correct about multithreading!
Unity3D's methods are mostly mono-thread and not thread-safe. However any 'static' field you make will be thread-safe after you use some of your System.Threading skills.
With this being said, using a static field as a wrapper for a Unity3D method may yield... unexpected results.
But basicly the only thing you can't do is use Unity API methods themselves across different threads, as they are not thread-safe

Although, you could, theoretically, pass variable information back to main thread using Deligates from a thread.
This was supposed to be tutorial for beginners. You don't need to complicate it with threading especially if stability is a hope, not reality. There is a better way to wait for an object to finish loading such as using Update.
In any case, with ModLoader 0.4 OnLoad has been delayed to running after black screen so you no longer need to wait for an object to finish loading.

Edit:
Forgot to mention. Yes you can multi-thread by using delegates and task system to pass info between threads in thread safe manner. I have done that in other unity projects. But work threads we're only calling .net APIs and once ready they would post a task onto unity thread which then would be picked up on the next available update cycle. There is a conference video on how to multi-thread unity games but the implementation is basically recreate unity APIs and pass just the data back to unity to draw.
 
Last edited:
This was supposed to be tutorial for beginners. You don't need to complicate it with threading especially if stability is a hope, not reality. There is a better way to wait for an object to finish loading such as using Update.
In any case, with ModLoader 0.4 OnLoad has been delayed to running after black screen so you no longer need to wait for an object to finish loading.

Edit:
Forgot to mention. Yes you can multi-thread by using delegates and task system to pass info between threads in thread safe manner. I have done that in other unity projects. But work threads we're only calling .net APIs and once ready they would post a task onto unity thread which then would be picked up on the next available update cycle. There is a conference video on how to multi-thread unity games but the implementation is basically recreate unity APIs and pass just the data back to unity to draw.

Thank you for the informative reply! This was mainly intended for beginners as I had to start somewhere but also for intermediate users or for the sake of not having to re-create the wheel all the time, even if it would be an easy or simple task. This would be usefull for everyone, that was the intention :)

I had the first "loading" in an Update method as the first option to make it more apparent that it would be the best way. I'm reviewing this as feedback basicly and perhaps that was not clear enough? I will adress this by removing theading for now :ninja:

Since 0.4 I need to update and remove parts of this guide for sure and the "loading thread" is no longer a useful snippet.

However, threading may be still prove useful or intressting for some modders in the future. Who knows... and this information may prove useful to that/those users then.
For now, untill I get more time on my hands to rework parts of the guide I will "remove" it untill I can basicly move it.

Thanks for taking your time and contributing! :thumbsup:
 
However, threading may be still prove useful or intressting for some modders in the future. Who knows... and this information may prove useful to that/those users then.

Unity Coroutines are safer that calling unity api from threading.
Coroutines has a little weird syntax but it works for async operations. Newer unity versions have better async functions, but we are stuck in 5.0.0f4.

Example you can replace this threading:
Code:
void Something()
{
   //Start thread worker
   new Thread(setup).Start();
}

void setup()
{
   Thread.Sleep(15 * 1000); // Wait for something 15 sec
   ModConsole.Print("Success!");
}

With this coroutine:
Code:
void Something()
{
   //Start coroutine
  StartCoroutine(setup());
}

IEnumerator setup()
{
   yield return new WaitForSeconds(15f); // Wait for something 15 sec
   ModConsole.Print("Success!");
}
One thing is just Coroutines is part of MonoBehaviour class.
 
Last edited:
Unity Coroutines are safer that calling unity api from threading.
Coroutines has a little weird syntax but it works for async operations. Newer unity versions have better async functions, but we are stuck in 5.0.0f4.
Coroutines is part of MonoBehaviour class.

Thanks, I have made some changes to "How to find the player" section but I have not gotten around to actually test/experiment with the newer versions. Untill I have tested and confirmed or someone else does confirm that for me.. It'll have to do for now :p

Agreed that Coroutines are preferable and the thing a modder should be using unless he is actually trying to do something heavy and time-consuming.
Although Coroutines have nothing to do with threads per say they can be used as an substitution for threads to be executed on the main thread. Coroutine methods can be executed piece by piece over time, but all processes are still done by the main thread. If a Coroutine attempts to execute time-consuming operation or anything on the main thread, the whole application freezes or experience lagg for the time it takes to process.
I'm just trying to cover all bases :)

I'm thinking about making a section covering threading and coroutines when I get the time i need!
I'm looking for as much concrete information/facts and opinions as I can on this aspect of programming!

It is always appreciated when examples and code-snippets are shared!:thumbsup:
 
Thanks, I have made some changes to "How to find the player" section but I have not gotten around to actually test/experiment with the newer versions. Untill I have tested and confirmed or someone else does confirm that for me.. It'll have to do for now
Since 0.4 OnLoad is called after player is ready (and all other gameobjects), so threading doesn't make sense, I see that <0.3.5 habits will die hard.
 
Since 0.4 OnLoad is called after player is ready (and all other gameobjects), so threading doesn't make sense, I see that <0.3.5 habits will die hard.
Honestly, I can't (really and certainly) name a situation where a user would need a thread unless a user was interested in making any of these:
  • AI
  • Pathfinding
  • Network communication
  • Files operations
  • Advanced Pooling
Lets face it though.. Even if I wanted to actually provide a guide (<--This would be where it made sens) on Threading or when it is/would be useful I think such a user has some previous experience and would not need this specific guide. Also, the zero interest isn't exactly what I was expecting to be honest.

Skipping threading and in-depth Coroutines.

Thanks :ninja:
 
I think this is supposed to be begginers guide? Threading is not easy stuff, you need to synchronize these threads and do other stuff, and also unity (at least 5.0.0) is not thread safe. Too much complexity to this type of guide.

Lets face it though.. Even if I wanted to actually provide a guide (<--This would be where it made sens) on Threading or when it is/would be useful I think such a user has some previous experience and would not need this specific guide. Also, the zero interest isn't exactly what I was expecting to be honest

Threading may be usefull, but you need to be carefull, try running simple GameObject.Find in separate thread in unity editor. It will compile fine, but when you play and hit that thread you get error that "this is allowed only in main thread", you get that error for almost all unity api functions.

Don't know why it is possible by mscloader, it mostly abuse something, and bad things can happen when both threads will try modify same gameobject at the same time.
 
Last edited:
This is exactly what I was talking about at the begining. Even in editor it will compile fine because it's difficult to create compile time checker for thread access. In any case, like noted before, this was begginer's tutorial and turning it into even intermediate lvl tutorial is pointless because those people already know what they are doing. Anything above beginner would appreciate code samples over slow tutorial.
 
Can I get an opinion on the best way to replace Teimo's hat? At the moment I'm replacing his hat model with an alien head in the game files, but doing it that way I can't figure out how to get the textures in as well, so it looks awful. If I were gonna try and take the plunge and try to learn how to make this a mod, would there be a way to get the textures running as well?

For reference :
at the moment he's just got a flat blue looking head. If anyone has an idea on how I could get the textures going too, lemme know!
 

Latest News

How long have you been simracing

  • < 1 year

    Votes: 312 15.5%
  • < 2 years

    Votes: 213 10.6%
  • < 3 years

    Votes: 207 10.3%
  • < 4 years

    Votes: 157 7.8%
  • < 5 years

    Votes: 271 13.5%
  • < 10 years

    Votes: 233 11.6%
  • < 15 years

    Votes: 150 7.5%
  • < 20 years

    Votes: 118 5.9%
  • < 25 years

    Votes: 89 4.4%
  • Ok, I am a dinosaur

    Votes: 261 13.0%
Back
Top