Documentation for lessons on making the Unturned mod.
Lesson #1 How to make object.
Hole Sizes
- Door - Width - 2.5m | Height - 2.8m
- Double door - Width - 4m | Height - 3.75m
- Window - Width - 4m | Height - 3m
- Hatch Width - 2m | Longitude - 2m.
Note: Rotation and Collider Size are not very important, if you have other sizes and coordinates, the slot will still work. But various bugs can occur, for example, incorrect attachment of the door to the slot. In addition, the slots match the hole sizes and Unturned models.
Exclusion
Ladder - When changing the size of the collider, you will change the size of the surface on which you can move, suitable for high ladders.
Slot: This slot is not only for the window, but also for glass and barricades, when increasing this collider, you can put glass and barricade around the entire perimeter, but the shutters will most likely hang in the air.
Name of Slots
- Door - for door
- Gate - for double door
- Slot - for window
- Hatch - for hatch
- Climb - for ladder
- Ladder - for surface of the ladder
Rotation coordinates for slots & collider size
- Door - X 90| Z -180. Collider: X 2.25 | Y 2.8
- Gate - X 90| Z 180. Collider: X 4 | Y 3.75
- Slot - X -90| Z -90. Collider: X 3 | Y 4
- Hatch - X -90| Z -180. Collider: X 2 | Z 2
- Climb - X -90| Z -90. Collider: X 4.25 | Y 1.5
- Ladder - Collider: X 1.2 | Y 0.2 | Z 4.25
Exclude_From_Master_Bundle
Asset_Bundle_Version 5
Useful Links
The purpose of the names Layers and Tags can be found at the link:
https://docs.smartlydressedgames.com/en/stable/assets/layers.html
Check the current Unturned version of Unity here:
https://docs.smartlydressedgames.com/en/stable/about/getting-started.html#installing-unity
Official Unturned documentation:
https://docs.smartlydressedgames.com/en/stable/index.html
Download Notepad++ here:
https://notepad-plus-plus.org/downloads/v8.6.7/
Download Unity Hub:
https://unity.com/download
Character Model:
https://skfb.ly/prR8H
GUID Generator:
https://www.guidgenerator.com/
Lesson #2 How to make Vehicle
Vehicle docs:
https://docs.smartlydressedgames.com/en/stable/assets/vehicle-asset.html
Preview Character:
https://drive.google.com/file/d/13qIjDE6zreo9-Ce1cldeK9lzE6w84qzb/view?usp=drive_link
Lesson #4 How to make Animals
Vehicle docs:
https://docs.smartlydressedgames.com/en/stable/assets/animal-asset.html
Multipliers to name your Bones
Skull_Multiplier:
Spine_Multiplier:
Leg Multipliers:
- Left_Front
- Right_Front
- Left_Back
- Right_Back
If your Bone is named something else the damage the Animal takes will be the Gun’s Base
Animal Damage.
Animation limitation in server
[At 30 frames]:
- Eat - 160
- Glance - 60
- Idle - 24
- Walk - 60
- Attack 60
- Startle - 19.
- Run - 9.
Lesson #5 How to make Resourses.
Useful Links
Scripts:
Billboard Generator Script:
using UnityEngine;
using UnityEditor;
using System.IO;
public class BillboardGeneratorWindow : EditorWindow
{
private int rows = 4; // Кількість рядів
private int columns = 2; // Кількість стовпців
private float billboardWidth = 5f;
private float billboardHeight = 10f;
[MenuItem("Tools/Billboard Generator")]
public static void ShowWindow()
{
GetWindow<BillboardGeneratorWindow>("Billboard Generator");
}
private void OnGUI()
{
GUILayout.Label("Налаштування Білборда", EditorStyles.boldLabel);
rows = EditorGUILayout.IntField("Кількість рядів", rows);
columns = EditorGUILayout.IntField("Кількість стовпців", columns);
billboardWidth = EditorGUILayout.FloatField("Ширина", billboardWidth);
billboardHeight = EditorGUILayout.FloatField("Висота", billboardHeight);
if (GUILayout.Button("Створити білборд"))
{
CreateBillboard(rows, columns, billboardWidth, billboardHeight);
}
}
private void CreateBillboard(int rows, int cols, float width, float height)
{
Texture2D selectedTexture = Selection.activeObject as Texture2D;
if (selectedTexture == null)
{
Debug.LogError("Будь ласка, виберіть текстуру перед створенням білборда!");
return;
}
string texturePath = AssetDatabase.GetAssetPath(selectedTexture);
string directory = Path.GetDirectoryName(texturePath);
string assetPath = Path.Combine(directory, "Billboard.asset");
BillboardAsset billboardAsset = new BillboardAsset();
billboardAsset.width = width;
billboardAsset.height = height;
billboardAsset.bottom = 0f;
// **Генерація UV координат на основі вибраного Grid Size**
Vector4[] uvCoords = new Vector4[rows * cols];
float rowHeight = 1f / rows;
float colWidth = 1f / cols;
int index = 0;
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
float x = col * colWidth;
float y = 1f - (row + 1) * rowHeight; // Відлік знизу вверх
uvCoords[index] = new Vector4(x, y, colWidth, rowHeight);
index++;
}
}
billboardAsset.SetImageTexCoords(uvCoords);
// **Вершини білборда**
billboardAsset.SetVertices(new Vector2[]
{
new Vector2(0f, 0f), // Лівий низ
new Vector2(0f, 1f), // Лівий верх
new Vector2(1f, 0f), // Правий низ
new Vector2(1f, 1f) // Правий верх
});
// **Індекси**
billboardAsset.SetIndices(new ushort[] { 0, 1, 2, 2, 1, 3 });
// **Матеріал**
Material billboardMaterial = new Material(Shader.Find("Unlit/Texture"));
billboardAsset.material = billboardMaterial;
// **Зберігаємо Asset**
AssetDatabase.CreateAsset(billboardAsset, assetPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"Billboard Asset створено: {assetPath}");
}
}
Billboard Texture Generator Script
using UnityEngine;
using UnityEditor;
using System.IO;
public class BillboardTextureGenerator : EditorWindow
{
private int textureSize = 512;
private float distanceMultiplier = 3f;
private string savePath = "Assets/BillboardTexture.png";
private int gridX = 2;
private int gridY = 4;
[MenuItem("Tools/Billboard Texture Generator")]
public static void ShowWindow()
{
GetWindow<BillboardTextureGenerator>("Billboard Generator");
}
private void OnGUI()
{
GUILayout.Label("Billboard Settings", EditorStyles.boldLabel);
textureSize = EditorGUILayout.IntField("Texture Size", textureSize);
distanceMultiplier = EditorGUILayout.FloatField("Distance Multiplier", distanceMultiplier);
gridX = EditorGUILayout.IntField("Grid X", gridX);
gridY = EditorGUILayout.IntField("Grid Y", gridY);
savePath = EditorGUILayout.TextField("Save Path", savePath);
if (GUILayout.Button("Generate Billboard"))
{
GenerateBillboard();
}
}
private void GenerateBillboard()
{
GameObject selectedObject = Selection.activeGameObject;
if (selectedObject == null)
{
Debug.LogError("No object selected! Please select a tree model in the scene.");
return;
}
Bounds bounds = GetBounds(selectedObject);
Vector3 center = bounds.center;
float radius = Mathf.Max(bounds.extents.x, bounds.extents.z);
float distance = radius * distanceMultiplier;
GameObject camObj = new GameObject("BillboardCamera");
Camera cam = camObj.AddComponent<Camera>();
cam.orthographic = false;
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = Color.clear;
cam.cullingMask = ~0;
cam.nearClipPlane = 0.1f;
cam.farClipPlane = distance * 2;
cam.fieldOfView = 30;
RenderTexture rt = new RenderTexture(textureSize, textureSize, 16);
cam.targetTexture = rt;
Texture2D finalTexture = new Texture2D(textureSize * gridX, textureSize * gridY, TextureFormat.ARGB32, false);
int totalFrames = gridX * gridY;
float angleStep = 360f / totalFrames;
for (int i = 0; i < totalFrames; i++)
{
float angle = i * angleStep;
Vector3 pos = center + Quaternion.Euler(0, angle, 0) * new Vector3(0, 0, -distance);
cam.transform.position = pos;
cam.transform.LookAt(center);
cam.Render();
RenderTexture.active = rt;
Texture2D tex = new Texture2D(textureSize, textureSize, TextureFormat.ARGB32, false);
tex.ReadPixels(new Rect(0, 0, textureSize, textureSize), 0, 0);
tex.Apply();
int x = (i % gridX) * textureSize;
int y = ((gridY - 1) - i / gridX) * textureSize;
finalTexture.SetPixels(x, y, textureSize, textureSize, tex.GetPixels());
Object.DestroyImmediate(tex);
}
finalTexture.Apply();
byte[] bytes = finalTexture.EncodeToPNG();
File.WriteAllBytes(savePath, bytes);
AssetDatabase.Refresh();
Object.DestroyImmediate(camObj);
RenderTexture.active = null;
Object.DestroyImmediate(rt);
Object.DestroyImmediate(finalTexture);
Debug.Log("Billboard texture saved at: " + savePath);
}
private static Bounds GetBounds(GameObject obj)
{
Renderer[] renderers = obj.GetComponentsInChildren<Renderer>();
if (renderers.Length == 0)
{
return new Bounds(obj.transform.position, Vector3.zero);
}
Bounds bounds = renderers[0].bounds;
foreach (Renderer renderer in renderers)
{
bounds.Encapsulate(renderer.bounds);
}
return bounds;
}
}