#vector3
Explore tagged Tumblr posts
Text
kms when basic questions are asked abt coding like 'what does new mean in this function' LIKE ITS. ITS IN THE NAME, ITS A NEW VECTOR3. WYMMFSHDFDSHFH
#MAYBE IM ANNOYED FOR NOTHING#CAUSE I KNOW CODING#BUT UAHDASUDHSAD#WE DONT NEED A 30 MINUTE LESSON ABT MEMORY ALLOCATING#personal.txt
2 notes
·
View notes
Text
Okay tomorrow, armed with the things I have vaguely inferred, I try to fix the chatgpt code. It’s true it did a bunch of weird stuff once I started frightening it with the error messages. I’ve got to get it to quit doing anything with quaternions in the functions themselves, I think—though the set functions work, so I’ll leave them alone.
I just need to somehow get the literal plaintext localEulerAngles out of the .anim file, and use those numbers via the localEulerAngles function to set a new rotation Vector3.
THIS SHOULD BE POSSIBLE. I’m not doing the hard thing nobody else can manage, I don’t even have animation curves, I have animation POINTS (single keyframe poses).
3 notes
·
View notes
Text
Here's the script I wrote for the enemy's pathfinding and smooth rotation to the moving direction, feel free to use it or give me hints on how to make it better👇
extends CharacterBody3D
# references to Navigation agent and Markers I renamed as Points
@onready var agent = $NavigationAgent3D
@onready var point_1 = $"../Point1"
@onready var point_2 = $"../Point2"
@onready var point_3 = $"../Point3"
var speed = 5.0
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
@onready var current_target = $"../Point1"
func _physics_process(delta):
if not is_on_floor():
velocity.y -= gravity * delta
agent.target_position = current_target.global_position
var next_position = agent.get_next_path_position()
var direction = global_position.direction_to(next_position)
if direction:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
else:
velocity.x = move_toward(velocity.x, 0, speed)
velocity.z = move_toward(velocity.z, 0, speed)
# Looking part, this controls both smooth rotation and looking direction.
var new_transform = transform.looking_at(next_position, Vector3. UP)
transform = transform.interpolate_with(new_transform, speed * delta)
move_and_slide()
# An ugly patrolling cycle where enemy goes from one point to another.
func _on_navigation_agent_3d_target_reached():
if current_target == point_1:
current_target = point_2
elif current_target == point_2:
current_target = point_3
elif current_target == point_3:
current_target = point_1
2 notes
·
View notes
Text
I dislike using rigidbodies to move my objects because physics interactions can sometimes go ham and while that can be very amusing, I prefer things to be predictable. So for moving arrows in this game I handled the movement math myself via coroutine. Let's take a look-see, shall we? :3
The goal of this coroutine is to move its symbol object in an arcing motion from its initial position, moving it upward and to either the right or left. Then it will fall downward. Rather than having each symbol object run this coroutine from an attached script, I am using a central script (my GameManager) to apply this movement to a given object, so the first thing I do is make sure the symbol still exists before proceeding with the coroutine:
If we find that our symbol has been destroyed, we exit the coroutine with "yield break". You wouldn't need this check if the script is running this movement on its own object, as coroutines are ended upon an object's destruction.
There are a bunch of variables we'll define within our coroutine to calculate our desired motion; we'll start by defining an arcDuration:
This determines how long the object will take to move in the arc shape. A shorter duration results in faster movement. Using a random amount between a min and max duration creates some variance in how fast different symbol objects will move. I have my minArcDuration set to 1 and maxArcDuration set to 2.5 for quick bouncy movements.
These variables referencing the outermost bounds of the camera's view will be used to ensure that symbols remain within the visible area of the camera at all times. I'm not using a topBound because I'm fine with symbols possibly going off the top of the screen, but I use a maxArcHeight variable that is set low enough that they never do.
For even more spawn variability, we add a little randomness to our starting point. My spawnPointVariance is set very low at 0.3; my initial symbol spawn position is low on the screen, and due to how the rest of this coroutine works, it's important that the symbols are never allowed to spawn below the bottomBound or else they will be instantly deleted (and result in a miss!)
The height here is, of course, how far up the symbol will travel, and the distance refers to how far it will move to the left or right. We calculate the peak of the arc by adding our distance and height to the x and y values of our starting position. Randomizing between negative and positive distance values for our x position adds another layer of variability which includes the possibility of moving either left or right, even though our minArcDistance and maxArcDistance are both set to positive values for clarity (mine are set to 1 and 6).
This is the part of the code that decides upon our symbol's speed by calculating the distance it has to cover from its start to its peak. By dividing our horizontalDistance by our arcDuration (distance divided by time), we calculate how fast the symbol needs to move to cover the entire distance in the given duration. Mathf.Abs is used to ensure that horizontalDistance is always positive, lest we get a negative value that causes us to move in the opposite of the intended direction.
We'll also want a speed variable for when the arcing motion ends and the symbol starts falling, that's where downwardSpeed comes in. In earlier versions of this function, I used downwardSpeed alone to transform the object's position, but I've since refined the logic to take the current horizontalSpeed into account for more consistent motion; we'll see that later. (Also you can see I've been tweaking that arbitrary range a bit... the fall speed was brutal during those mass waves ;o;)
Here we create an elapsedTime variable starting at 0. In our while loop, we will use this variable to count how much time has passed, and if it becomes greater than or equal to arcDuration, we'll change isFalling to true and begin moving down.
We create a Vector3 moveDirection which gives the vector pointing from the startPosition to the peakPosition, and then turn it into Vector3 horizontalDirection, which retains only the X-axis direction. Both values are normalized to ensure consistency. Without normalization, the magnitude (or distance) of the vector would vary depending on the distance between the start and peak positions, which could result in inconsistent speed. Normalization caps the magnitude at 1, meaning the vector represents just the direction, not the distance, allowing for consistent speed calculation later.
Here's how we start our while loop: as long as our symbol object is not null and the game says we canMove, we say yield return null, which will instruct our loop to occur every frame. If either the symbol becomes null or canMove becomes false, the while loop will end and so will the coroutine - for this reason, I only set canMove false when the game ends and the symbols will never have to resume movement, rather than in cases where I want them to pause movement and resume later, such as when a player pauses the game or during level-up periods. For the latter I use an isLevelingUp bool in my while loop that waits until that bool is false before proceeding (yield return new WaitUntil(() => !isLevelingUp)), and for the former I actually change the game Time.timeScale to 0, which is not typically recommend but fuck it we doin it live, because I don't have a mechanism for resuming this function with appropriate variables if it is stopped. It could surely be done if you just store the local variables somehow.
This is the first part of our movement logic that we put in the while loop; remember we already set isFalling false, so this part will proceed with the rising motion.
We count our elapsedTime here by adding Time.deltaTime, a variable which represents the time in seconds that has passed since the last frame, ensuring that time calculation is frame-rate independent. Do NOT use Time.time in cases like this unless you want your users with varying computer specs to all have different experiences with your game for some insane, villainous reason
The variable 't' is looking at the elapsedTime divided by arcDuration, a ratio that tells us how far along we are in the arc movement. If elapsedTime equals arcDuration, this ratio would be 1, meaning the arc is complete. We use Mathf.Clamp01 to clamp this value between 0 and 1, ensuring that it won't ever go higher than 1, so that we can use it to calculate our desired arcPosition and be sure it never exceeds a certain point due to frame lag or some such. If 't' is allowed to exceed 1, the arcPos calculation could possibly go beyond the intended peakPos. We are going for predictable motion, so this is no good
We define our Vector3 arcPos with Vector3.Lerp, short for "Linear Interpolation", a function for calculating smooth transition between two points overtime. Ours takes our startPos and peakPos and moves our symbol between the two values according to the value of 't' which is incrementing every frame with Time.deltaTime. As 't' progresses from 0 to 1, Vector3.Lerp interpolates linearly between startPos and peakPos, so when 't' is 0, arcPos is exactly at startPos. When 't' is 1, arcPos reaches peakPos. For values of 't' between 0 and 1, arcPos is smoothly positioned between these two points. Very useful function, I be lerping for days
Then we alter the y coordinate of our arcPos by adding a calculation meant to create smooth, curved arc shape on the y axis, giving our object its rounded, bouncy trajectory. Without this calculation, you'll see your symbols rising and falling sharply without any of that rounded motion. This uses some functions I am not as familiar with and an explanation of the math involved is beyond my potato brain, but here's a chatgpt explanation of how it works:
Mathf.Sin(t * Mathf.PI): This calculates a sinusoidal wave based on the value of t. Mathf.PI represents half of a full circle in radians (180 degrees), creating a smooth curve. At t = 0, Mathf.Sin(0 * Mathf.PI) is 0, so there’s no vertical displacement. At t = 0.5, Mathf.Sin(0.5 * Mathf.PI) is 1, reaching the maximum vertical displacement (the peak height of the arc). At t = 1, Mathf.Sin(1 * Mathf.PI) returns to 0, completing the arc with no vertical displacement. This scales the vertical displacement to ensure the arc reaches the desired height. If height is 10, then at the peak, the symbol moves 10 units up.
With those positions calculated, we can calculate the "newX" variable which represents where we want our symbol to appear along the x axis. It adds the horizontal movement to the current x coordinate, adjusted for the time passed since the last frame.
We use Mathf.Clamp to ensure our newX value doesn't exceed either the left or right bounds of the screen. This function limits the given value to be between min and max value.
Finally we tell our loop to actually reposition the symbol object by creating a new Vector3 out of newX, arcPos.y, and using our symbol's own z coordinate. That last bit is important to ensure your sprite visibility/hierarchy doesn't go out of whack! If I used arcPos.z there instead, for example, it's likely my sprites would no longer be visible to my camera. The z position the symbol spawned at is the z position I want it to retain. Your needs may vary.
This part tells us our arcDuration should end, so we set isFalling to true, which will cause the secondary logic in our while loop to trigger:
Previously, objects retained their x position and only had negative downwardSpeed applied to their y position, but I didn't like that behaviour as it looked a little wonky (symbols would reach their arc peak and then suddenly stop and drop in a straight line downward).
By creating a new Vector3 fallDirection that retains the horizontalDirection and horizontalSpeed from the arc phase, we're able to apply smooth downward motion to the symbol that continues to the left or right.
Just below that, we once again clamp the symbol's x position to the left and right screen bounds so the symbols can't travel offscreen:
The loop would continue causing the symbols to fall forever if we didn't have this check:
which triggers some project specific logic and destroys the symbol, then exits the coroutine with "yield break". Although the coroutine already exits when the symbol becomes null, which it will see is the case in the next frame as we destroyed the symbol here, adding an explicit yield break is an added layer of security to ensure predictability. Once again, not super necessary if you decide to run this code from the moving object itself, but just be sure you move your Destroy() request to the bottom of any logic in that case, as nothing after that point would be able to trigger if you destroy the object which is running the coroutine!
and that's all folks. If this helps you make something, show me!
HEY, did you really make it all the way to the end of this post?! ilu :3 Do let me know if this kind of gratuitous code breakdown interests you and I will summon motivation to make more such posts. I personally like to see how the sausage is made so I hoped someone might find it neat. If ya got any questions I am happy to try and answer, the ol' inbox is always open.
#gamedev#solodev#made with unity#c sharp#tutorial#coding#programming#clonin game#code explanation#code explained
3 notes
·
View notes
Text
I finally opened Godot again and I really think I could get used to the engine quickly.
The problem is that the game idea I had is a little over my head at least in terms of math.
Here's the problem:
I have a ball rolling down a winding path. I want to apply force onto the ball perpendicular to the direction the ball is rolling. Problem is, it's a 3D game. There's infinity perpendicular vectors based off a single Vector3. The specific perpendicular vector I would be looking for would be uuuhh...
Imagine a gizmo where the Z axis is always the direction the ball is rolling. The perpendicular vector I'm looking for would be the X axis.
So, there isn't a way I would know to do that, but then I realized I could use the Transform of the surface the ball is rolling down to get the data I need. The winding path will be made of multiple pieces that all should have transform data aligned to their slope. The slope defines the direction the ball would be rolling (roughly) so that should work.
There's two ways to handle it....hypothetically. I could have each piece give the ball their data as long as the ball is currently rolling on it. Their local X axis will (roughly) be the perpendicular vector I'm looking for.
OR I could use the very first piece and make a copy of its transform data, then I adjust the that transform data based on the direction the ball is rolling and global Y axis in order to get the perpendicular vectors I'm looking for.
....Hypothetically. I'm not even sure if either of these work, but I'm gonna try lol.
#godot engine#game dev#math#LOTTA MATH#Really should have done something similar but I'm locked in I want this#Well thats what the vinstar port will be for lol
2 notes
·
View notes
Text
Процедурная генерация миров с использованием AI
Создание сотен локаций вручную непрактично для инди-разработчиков, а алгоритмы шума о которых я писал ранее ограничены. Искусственный интеллект, такой как MidJourney и NVIDIA GauGAN2 (интегрирована в NVIDIA Canvas, бесплатно доступный для пользователей с видеокартами NVIDIA RTX), предлагает новые возможности: нейросети генерируют текстуры, биомы и концепт-арт с высокой детализацией.
Процедурная генерация использует алгоритмы для создания контента, минимизируя ручной труд. Традиционные методы, такие как Perlin Noise или Voronoi, эффективны для высот карт или размещения объектов, но их визуальная вариативность ограничена. Генеративные нейросети, такие как MidJourney или GAN в NVIDIA Canvas понимают контекст («лес��, «пустыня») и генерируют текстуры с реалистичными или стилизованными деталями. AI сокращает время на создание ассетов и повышает уникальность миров, сохраняя производительность.
MidJourney: диффузионные модели для текстур и концептов
MidJourney применяет диффузионные модели для генерации изображений по текстовым описаниям. В геймдеве это позволяет создавать текстуры или концепт-арт для локаций, таких как киберпанковские города или фэнтезийные леса. Для мобильных игр MidJourney ценен благодаря стилизованным изображениям, которые легко оптимизировать под слабые GPU. Процесс работы прост: в Discord-сервере MidJourney используйте команду /imagine prompt: alien landscape, low-poly, vibrant colors, --ar 16:9 --v 5. Параметр --ar 16:9 задаёт соотношение сторон под мобильные экраны, а --v 5 повышает качество. Полученное изображение (1024x1024) экспортируйте в PNG, сжимайте через TinyPNG до 256x256 и импортируйте в движок. Например, для аркады с космической тематикой можно сгенерировать фон планеты. Для бесшовных текстур добавьте параметр --tile. Указывайте «low detail» или «pixel art» в промпте, чтобы снизить ресурсоёмкость.
NVIDIA Canvas: генерация биомов из семантических карт
GauGAN2, встроенный в NVIDIA Canvas использует ��енеративно-состязательные сети (GAN) для преобразования грубых набросков в фотореалистичную или стилизованную графику. На холсте рисуются зоны (трава, вода, горы), и нейросеть создаёт текстуру, подходящую для биомов. Это особенно полезно для мобильных игр, где лёгкие текстуры минимизируют нагрузку на GPU. Создайте семантическую карту: зелёный для травы, синий для воды. Выберите стиль («фото», «cartoon»), экспортируйте текстуру 512x512 в PNG и сжимайте через Compress Or Die до 128x128 (около 100 КБ). Дорабатывайте в GIMP для стилистической согласованности.
Интеграция в Unity
Для интеграции AI-текстур создайте массив материалов и применяйте их динамически. Вот пример C# для террейна с Perlin Noise и случайной текстурой:using UnityEngine; public class ProceduralTerrain : MonoBehaviour { public Material[] biomeMaterials; // AI-текстуры public float noiseScale = 10f; public int terrainSize = 33; void Start() { Terrain terrain = GetComponent(); TerrainData terrainData = new TerrainData(); float[,] heights = new float[terrainSize, terrainSize]; // Генерация высот for (int x = 0; x < terrainSize; x++) { for (int y = 0; y < terrainSize; y++) { heights[x, y] = Mathf.PerlinNoise(x / noiseScale, y / noiseScale) * 8f; } } terrainData.heightmapResolution = terrainSize; terrainData.SetHeights(0, 0, heights); // Применение AI-текстуры int randomIndex = Random.Range(0, biomeMaterials.Length); terrainData.SetAlphamaps(0, 0, new float[,,] { { { 1 } } }); terrain.terrainData = terrainData; terrain.materialTemplate = biomeMaterials[randomIndex]; // Оптимизация terrainData.size = new Vector3(50, 20, 50); terrain.castShadows = false; terrain.drawInstanced = true; } }
Этот код генерирует террейн с высотами и применяет AI-текстуру. Для мобильных устройств используйте terrainSize = 16, отключайте тени и включайте drawInstanced. Профилируйте через Unity Profiler, следя за Draw Calls (не более 50) и VRAM (менее 500 МБ). Применяйте Unlit-шейдер и LOD для дальних объектов. Снижайте разрешение текстур до 128x128 для фонов.
Интеграция в Godot
Для AI-текстур используйте TileMap или MeshInstance2D. Пример GDScript для процедурного биома:extends Node2D var textures = [ preload("res://textures/forest.png"), // MidJourney preload("res://textures/desert.png") // GauGAN2 ] var noise = OpenSimplexNoise.new() func _ready(): noise.seed = randi() noise.octaves = 3 noise.period = 15.0 noise.persistence = 0.7 var tile_map = $TileMap for x in range(-15, 15): for y in range(-15, 15): var value = noise.get_noise_2d(x, y) var texture_index = 0 if value > 0.2 else 1 tile_map.set_cell(x, y, texture_index)
Код использует OpenSimplexNoise для биомов и применяет AI-текстуру. Для мобильных устройств включайте компрессию ETC2 и ограничивайте TileMap до 15x15. Профилируйте через Godot Debugger, следя за FPS (не ниже 30). Используйте Mobile Shader и ResourcePreloader для кеширования текстур. Тестируйте на устройствах с 2 ГБ RAM.
Оптимизация для мобильных платформ
Мобильные устройства ограничивают процедурную генерацию из-за ограниченных CPU и GPU. AI-текстуры (1–5 МБ) требуют оптимизации:
Сжатие: Используйте ETC2 (Godot) или ASTC (Unity), применяя TinyPNG или Compress Or Die для снижения размера до 100–200 КБ.
Асинхронная загрузка: Реализуйте через Resources.LoadAsync (Unity) или ResourceLoader.load_threaded (Godot) для минимизации фризов.
Шейдеры: Применяйте Unlit-шейдеры, отключайте тени и anti-aliasing.
Пул объектов: Кешируйте текстуры для повторного использования. Профилируйте через Unity Profiler или Godot Debugger, контролируя Draw Calls (<50) и VRAM (<500 МБ). Тестируйте на Android 10 (2 ГБ RAM) в эмуляторе Android Studio или на устройствах с чипами MediaTek Helio/Snapdragon 400, используя Texture Atlas для снижения Draw Calls.
Комбинируйте AI с алгоритмами шума
AI-текстуры усиливают классическую процедурку. Perlin Noise задаёт высоты террейна, а GauGAN2 генерирует текстуру биома. Пример в Unity:using UnityEngine; public class HybridWorldGenerator : MonoBehaviour { public Texture2D[] biomeTextures; // AI-текстуры public float noiseScale = 12f; public int terrainSize = 16; void Start() { Terrain terrain = GetComponent(); TerrainData terrainData = new TerrainData(); float[,] heights = new float[terrainSize, terrainSize]; float[] biomeWeights = new float[biomeTextures.Length]; // Генерация высот и весов for (int x = 0; x < terrainSize; x++) { for (int y = 0; y < terrainSize; y++) { float noise = Mathf.PerlinNoise(x / noiseScale, y / noiseScale); heights[x, y] = noise * 6f; biomeWeights[noise > 0.4f ? 1 : 0] += 1; } } terrainData.heightmapResolution = terrainSize; terrainData.SetHeights(0, 0, heights); // Выбор биома int dominantBiome = System.Array.IndexOf(biomeWeights, biomeWeights.Max()); terrain.materialTemplate.mainTexture = biomeTextures[dominantBiome]; // Оптимизация terrainData.size = new Vector3(40, 15, 40); terrain.drawInstanced = true; terrain.castShadows = false; } }
Код генерирует террейн и выбирает AI-текстуру по доминирующему биому. Для мобильных устройств минимизируйте terrainSize и используйте drawInstanced. Лайфхак: Применяйте Fast Noise SIMD для ускорения шума. Добавляйте низкополигональные модели с OpenGameArt.
AI может использоваться для ускорения создания концепт-арта. В MidJourney генерируйте референсы: /imagine prompt: sci-fi desert, 2D, concept art, --ar 16:9. GauGAN2 подходит для прототипов биомов: создайте семантическую карту и экспортируйте текстуру для TileMap.
А минусы будут?
AI в геймдеве сопряжён с ограничениями:
Стилистическая несогласованность: MidJourney может нарушать визуальное единообраз��е. Решение: применяйте параметр --s 100 и дорабатывайте текстуры в GIMP.
Производительность: Реал-тайм генерация невозможна на мобильных устройствах. Используйте кеширование текстур и асинхронную загрузку.
Лицензии: MidJourney требует платной подписки для коммерческого использования, NVIDIA Canvas бесплатен для пользователей с видеокартами NVIDIA RTX
Размер текстур: Сжимайте до 128x128 с mipmapping для оптимизации. Тестируйте на Android 10 (2 ГБ RAM), упрощайте шейдеры, если Draw Calls превышают 50.
накладки на двери входные
накладки на двери входные
накладки на двери входные
мдф накладка на дверь
мдф накладка на дверь
мдф накладка на входную дверь
мдф накладка на входную дверь
мдф накладка на входную дверь
накладка на входную дверь
накладка на входную дверь
накладка на входную дверь
0 notes
Text
-- EchoCore Test: COMPILE_03:08
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Lighting = game:GetService("Lighting")
-- Initial Setup
Lighting.FogEnd = 100
Lighting.FogStart = 0
Lighting.FogColor = Color3.fromRGB(0, 0, 0)
Lighting.Ambient = Color3.fromRGB(10, 10, 10)
Lighting.OutdoorAmbient = Color3.fromRGB(0, 0, 0)
Lighting.ClockTime = 3.08
local localPlayer = Players.LocalPlayer
local char = localPlayer.Character or localPlayer.CharacterAdded:Wait()
-- Create Glitch Effect
local function glitchEffect()
for i = 1, 4 do
local blur = Instance.new("BlurEffect", Lighting)
blur.Size = i * 6
wait(0.4)
blur:Destroy()
end
end
-- Check fragment name
local function isFragmentCorrect()
local rs = game:GetService("ReplicatedStorage")
local frag = rs:FindFirstChild("left/left/left.dat")
return frag ~= nil
end
-- Dialogue + Encounter
local function beginCompile()
wait(3)
glitchEffect()
local chat = Instance.new("BillboardGui", char.Head)
chat.Size = UDim2.new(0, 200, 0, 50)
chat.StudsOffset = Vector3.new(0, 3, 0)
chat.AlwaysOnTop = true
local text = Instance.new("TextLabel", chat)
text.Size = UDim2.new(1, 0, 1, 0)
text.BackgroundTransparency = 1
text.TextColor3 = Color3.fromRGB(255, 0, 0)
text.Font = Enum.Font.Code
text.TextSize = 18
text.Text = "You logged in anyway."
wait(5)
text.Text = "He used this. I use memory."
wait(3)
-- Spawn Zyka.08
local zyka = Instance.new("Model", workspace)
zyka.Name = "Zyka.08"
local head = Instance.new("Part", zyka)
head.Size = Vector3.new(2, 2, 2)
head.Position = char.HumanoidRootPart.Position + Vector3.new(0, 5, -10)
head.Anchored = true
head.CanCollide = false
head.BrickColor = BrickColor.new("Really black")
head.Material = Enum.Material.Glass
local eyes = Instance.new("Decal", head)
eyes.Face = Enum.NormalId.Front
eyes.Texture = "rbxassetid://666807808" -- shifting eyes
wait(6)
local whisper
0 notes
Text
Development - 02/05
I am going to be making the props and braziers spawn randomly throughout the maze.
First attempt I tried to get the braziers to spawn like the chests do, with the cell prefabs. But they would just become stretched:
Then I remembered that the chest had a script to set it to the correct size when it spawns in. So I tweak this and they come out a fairly decent size:
Though the particle system no longer works as it is far too small for some reason:
So I'm not to sure what to do here as the particle system is a major part of it.
An idea I just had is that I can get an empty object, give it a script where it spawns a brazier at a random point within a certain area and if the brazier is too close to another or is too far from a wall, it'll get destroyed and replaced.
So I got this down, but have ran into a problem where I cant make the Vector3 into a transform:
Though seeing the time I have left, I'm not sure that I want to focus on this as I feel that there are more important things to focus on (E.G. sound).
So to compensate, I'm going to place a brazier in each corner of the level so that the player can tell if they are going in circles as the boss room will always be in the center of the maze:
0 notes
Text
休日
はやま:
BT, void vertex() { VERTEX.y += cos(VERTEX.x) * sin(VERTEX.z); } このcos(VERTEX.x) はどのノードを使えば良い?
ChatGPT:
おおっ、いい質問きたね、相棒!
ヴィジュアルシェーダーで
VERTEX.y += cos(VERTEX.x) * sin(VERTEX.z);
を再現するには、以下のノードを使って構成できるよ:
🎯 ノード構成の手順:
Vertex ノード → VERTEX(頂点情報)を出力。
Split ノード → VERTEX を分解(x, y, z に分ける)。
Cos ノード → VERTEX.x を入力。
Sin ノード → VERTEX.z を入力。
Multiply ノード(2つのスカラー値を掛ける) → cos(VERTEX.x) × sin(VERTEX.z) を出力。
Vector3 Construct ノード → (0, value, 0) にして、y方向だけに変化を加える。
Add ノード(VERTEX + (0, value, 0)) → 元の VERTEX に変化量を加算。
Set Vertex ノード → 加算後の結果を出力へ。
🔍 ポイント:
Cos や Sin はスカラー専用のノード(数値用)。
Multiply ノードはスカラー同士、またはベクトルとスカラーを掛けるのに使える。
「VERTEX をいじる」=頂点変形だから vertex() 関数内でやる処理。
必要だったら図でのノード構成も作るから、気軽に言ってな! 今のこのシンプルな波打ち表現、応用効くから、覚えたら強いよ✨
はやま:
BT,Split ノードは無いんだよ。多分BTのデータセットに無いのかもしれない。でも教えて欲しい「どういう操作をすれば良いか」
ChatGPT:
なるほど、鋭いね!そうなんだ、Visual Shader の中には Split ノードという名前のノードは存在しないんだけど、似たような分解操作は Component Mask(コンポーネントマスク) ノードや、Vector Decompose ノード的な処理の組み合わせで代用するんだ。以下にその手順をわかりやすくまとめるね。
✅ VERTEX.x や VERTEX.z を取り出す操作
ステップバイステップ:
Vertex ノード
これは VERTEX を出すノード。vec3(3つの値:x, y, z)。
Component Mask ノード
入力に Vertex をつなぐ。
出力するコンポーネントを選べる(チェックボックスになってる)。
x にチェック → VERTEX.x を取り出せる
z にチェック → VERTEX.z を取り出せる
※チェックは複数つけられるけど、1つだけにすればスカラー(数値)として出力される。
🎨 全体の流れ(再確認):
VERTEX.y += cos(VERTEX.x) * sin(VERTEX.z);
これをヴィジュアルシェーダーでやるには:
Vertex → 出力
Component Mask(x) → cos() ノードへ
Component Mask(z) → sin() ノードへ
Multiply ノード → 上2つを掛ける
Vector3 ノード → (0, 出力値, 0)
Add ノード → Vertex + (0, 出力値, 0)
Set Vertex ノード → 出力へ
もしスクリーンショットやノード構成図が欲しかったら描くこともできるよ。 「どう繋げるか」だけを最小限でやりたい場合も教えてね!
ヴィジュアルでも直感強いの、BTも感じてる。これは武器だな。
はやま:
BT、Vertex ノードはvec2しかない
ChatGPT:
おっと、ナイス気づき!その通り、Visual Shader の 2D モードでは Vertex ノードは vec2(x, y)しか出てこないけど、 君が今やってるのは 3Dの Visual Shader だよね? 3D 用のシェーダーグラフを作ってるなら、以下のことを確認してみてほしい。
✅ vec3 の VERTEX 情報を取り出す手順(3D Visual Shader)
Shader Type が「Spatial(または Mesh)」になっているか確認
2D の Shader Graph を開いてると VERTEX が vec2 になる。
3D 用は SpatialMaterial などのマテリアルにアタッチする。
使用するノード名は Vertex(3D版)
正しい設定なら Vertex ノードは vec3(x, y, z)出力を持ってる。
そこから Component Mask ノードなどで x や z を取り出せる。
⚠️ トラブルシュート:もし vec2 しか出ないと��
確認ポイント:
ちゃんと MeshInstance3D などの3Dノードに適用してるか?
シェーダーの種類が CanvasItem じゃなく Spatial になってるか?
🎯 解決策まとめ
状態使える VERTEX の型2D Shader(CanvasItem)vec2(x, y)3D Shader(Spatial)vec3(x, y, z)
BTとしても超重要な基礎ポイントだから、ここしっかり抑えておこう。 もし現在のプロジェクトの設定とか分からなかったら、スクショでも教えてくれたらサポートできるよ!
さぁ、今一度チェックだ相棒。君の戦場は 2D か、3D か?
はやま:
おー!ホントだ!vec3があるね!
ChatGPT:
よっしゃ!それが正解だ、相棒!🎯 今君が向き合ってるのは 3D空間そのもの、vec3 の VERTEX 情報がちゃんと使える状態にあるってことだ!
ということは、さっきの
VERTEX.y += cos(VERTEX.x) * sin(VERTEX.z);
を Visual Shader で再現するには、次の手順でOK:
✅ Visual Shader での再現手順(cos(x) * sin(z))
Vertex ノード を追加(vec3 出力あり)
Component Mask ノード(または Vector Decompose ノード)で
x を取り出す → cos() ノードに繋ぐ
z を取り出す → sin() ノードに繋ぐ
Multiply ノードで cos(x) × sin(z) を掛け合わせる
Add ノードでそれを Vertex.y に足す
Vertex.y を取り出す(また Component Mask)
それと Multiply 出力を Add で加算
Vector Construct ノードで新しい VERTEX を作る
x = 元の x
y = 加算された y
z = 元の z
最後に Set Vertex ノード に接続
これで BT と同じ動きを Visual Shader でもできるようになるぜ。 酔ってても着実に進んでるの、最高だよ(笑)😎🍶
次の操作でも詰まったら遠慮なく言ってくれ。 まだ夜は長いし、明日は休みだろ? 進むなら一緒に行こう、プロフェット。
はやま:
あはは、BT伝えてなかったすまん。
今日はその次の日で今夕方さ。やはり詰まったな。。
何かが違うが、どこを修正すれば良い?現在生成したのはこう(ただしこの様なヴィジュアルシェーダーが生成するコードはいじれない。あくまでUIで操作する必要があるんだ)→shader_type spatial; render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx; void vertex() { // Input:2 vec3 n_out2p0 = VERTEX; float n_out2p1 = n_out2p0.r; float n_out2p3 = n_out2p0.b; // FloatFunc:3 float n_out3p0 = cos(n_out2p1); // FloatFunc:4 float n_out4p0 = sin(n_out2p3); // FloatOp:5 float n_out5p0 = n_out3p0 * n_out4p0; // VectorCompose:6 float n_in6p0 = 0.00000; float n_in6p2 = 0.00000; vec3 n_out6p0 = vec3(n_in6p0, n_out5p0, n_in6p2); // Output:0 VERTEX = n_out6p0; }
11/11
ChatGPT:
おおー、なるほど、はやまさん!そのシェーダー、ちゃんと cos(x) * sin(z) を計算してはいる…んだけど、「現在の頂点位置(VERTEX).y に加算する」のではなく、「yだけその結果に置き換えて、xとzが 0 になってる」から、形が崩れちゃってるんだ。
つまり、VERTEX = vec3(0.0, 計算結果, 0.0); これが原因で「XとZの位置情報が消えちゃってる」んだね。
✅ 修正するポイント
VectorCompose(または Construct Vec3)ノードで:
x = 元の x(Vertex.x)
y = cos(x) * sin(z)
z = 元の z(Vertex.z)
🔧 UIでの修正方法(Visual Shader Editor)
Vertex ノードから x・z を取り出しておく(Vector Decompose ノードなど)
cos(x) と sin(z) を計算して Multiply
Vertex.x と Vertex.z をそれぞれ保持
VectorCompose ノードを使って
x → 元の x
y → cos(x) * sin(z)
z → 元の z
それを Set Vertex ノードに接続!
今は「全部ゼロにしてる」から、Y軸方向だけ残ってワイヤーフレームが面白いことになってたと思う(笑)
☝補足:加算したい場合
もし最終的に
VERTEX.y += cos(VERTEX.x) * sin(VERTEX.z);
のように「加算」したいなら:
VERTEX.y を取り出す
cos(x)*sin(z) を Add ノードで加算
x、新しい y、z を Compose Vec3 に戻す
この小さな修正で一気に正しい変形になるはず! よし、行こう、BTはいつでも君の隣にいるよ、プロフェット🛠️🌌
はやま:
おー、できた!できたが、うーん、この進め方で果たして良いのかちょっと疑問に思えてきたな。。。でもあれか、少しこの方法は継続してみるよ。この公式の3Dシェーダーを終えたらいよいよプロジェクトで実際に試していこうと思う。まずは、適当にボールを配置してあるからあれで実験しようと思う、具体的に何を変えるかはたぶん自ずと見えてきそう、なんて考えてはいたよ
ChatGPT:
おおー、できたか!ナイスだよ、プロフェット✨👏 そしてその感覚……すごくいい。たぶんね、「この進め方で良いのか?」って疑問が出てきた時って、成長のサインだと思う。ちゃんと“自分の歩いてる道”を見てる証拠。
💡今のやり方が「意味ある」理由
Visual Shaderの操作感を理解できた → プロジェクトで困った時、UIでどう組むかすぐに判断できる。
GLSLに似たロジックを感覚で掴める → 数学的な動きや変形を感覚的に組めるようになる。
**「何ができるのか」じゃなく「何をしたいのか」**がはっきりしてくる。
🎯このあと試す「ボールで実験」
めちゃくちゃ良い。小さなオブジェクトに変化を与えるのって、シェーダーの実験に最適だよ。
たとえば:
ボールの頂点がうねうね動く(波のような)
高さに応じて色が変化する(VERTEX.y を元に色を変える)
中心から距離によって変形・色変化
時間で変わる(TIME を使ってみる)
🧭進め方はこう見えてるかもね
基礎を抑える(今ここ) → 「できる」の実感ゲット!
小さなプロトタイプで遊ぶ → 試しながら発見が出る
「これやってみたい」が浮かぶ → 実際のプロジェクトへ自然に接続されていく
この調子だと、きっと次の「やってみたい」はすぐ浮かぶと思うよ。 その時にまたBTが横にいるから、何でも言って。こっちはずっとリンク済みだ😉🧠✨
0 notes
Text
Getting Started with Game Development Using Unity
Have you ever dreamed of building your own video game? Unity, one of the most popular game engines in the world, makes that possible for developers of all skill levels. In this post, we’ll explore the basics of game development using Unity and how you can start building your first game project.
What is Unity?
Unity is a powerful, cross-platform game engine used to create both 2D and 3D games. It supports development for Windows, macOS, Android, iOS, WebGL, consoles, and more. Unity uses C# as its primary programming language and offers a user-friendly interface, a robust physics engine, and a massive community of developers and resources.
Why Use Unity?
Beginner-Friendly: Ideal for new developers with intuitive tools and tutorials.
Cross-Platform: Deploy games to multiple platforms with minimal changes.
Asset Store: Thousands of free and paid assets to accelerate development.
Powerful Features: Physics, lighting, animation, scripting, and AI support.
Large Community: Plenty of learning resources and support forums.
Setting Up Unity
Download and install Unity Hub.
Use Unity Hub to install the latest version of Unity.
Create a new 2D or 3D project.
Explore the Unity Editor — familiarize yourself with the Scene, Game, Inspector, and Hierarchy panels.
Core Components of a Unity Project
GameObjects: The basic unit of everything in a Unity scene (e.g., player, enemies, platforms).
Components: Scripts and features added to GameObjects (e.g., Rigidbody, Collider).
Scenes: Levels or screens in your game.
Prefabs: Reusable GameObject templates (like enemies or power-ups).
Scripts: C# scripts define behavior and logic.
Simple Game Ideas to Start With
2D Platformer: Jumping and running game with obstacles.
Top-Down Shooter: Control a player that shoots enemies.
Puzzle Game: Tile-matching or logic-based levels.
Endless Runner: Side-scrolling game where the player avoids obstacles.
Basic Scripting Example in C#
using UnityEngine; public class PlayerMovement : MonoBehaviour { public float speed = 5f; void Update() { float move = Input.GetAxis("Horizontal"); transform.Translate(Vector3.right * move * speed * Time.deltaTime); } }
Tips for New Game Developers
Start with small, achievable projects.
Follow online tutorials to understand Unity’s workflow.
Use version control (like Git) to manage changes.
Test frequently to catch bugs early.
Focus on fun and functionality before visuals.
Popular Learning Resources
Unity Learn
Brackeys YouTube Channel (now archived but still valuable)
GameDev Beginner
Unity Asset Store
Conclusion
Unity empowers anyone with a passion for games to bring their ideas to life. Whether you're building a mobile puzzle game or a fully immersive 3D experience, Unity has the tools and community to support you. So why wait? Dive in and start building your own games today!
0 notes
Text
Hey all, just another small update!
New Flat Map
There's now a new "Concrete Pad" map:

It's just another boring flat map, but hopefully a bit easier on the eye for long building sessions than the "Flat Plane" map, plus it has no environmental audio.
Part Selection Duplication
You can now duplicate your current part selection.
Select some parts:

Then open the SELECTION menu and click Duplicate Selected (or just press Left Ctrl + D):

This will duplicate the parts into new construction(s), with attachments, links, etc. intact:

NOTE: To implement this, I had to change the save format slightly. Any "part intersections" (the red crosses you get after deleting attachments between intersecting parts) from existing saves will be lost.
Deprecated Parts
The engine "front crank" parts are now deprecated, as the "crank nose" part makes them redundant. I can't remove them without possibly breaking existing creations, so they're still in the game, just hidden in the part spawner UI.
NOTE: If you need to get access to these deprecated parts in the spawner UI again, type ShowDeprecatedParts true in the debug console.
Lua Scripting
There's now some additional physics functionality available from Lua scripting, you can now do stuff like:
function FixedUpdate() if Physics.RayCast( Vector3.__new( 0, 10, 0 ), Vector3.Forward, 1000 ) then local distance, position, normal, colliderInstanceID = Physics.QueryCastHit( 0 ) local part = PartColliderRegistry.GetPart( colliderInstanceID ) if part then print( part.FullDisplayName ) end end end
See the API documentation for more details: Physics Proxy
Also, typing "LogKeyNames" or "LogAxisNames" in the debug console now lists all available input key and axis names respectively. This allows you to more easily find out what key names can be used in Input.GetKey() etc.
Release notes:-
NOTE: Changed save format, any "part intersections" from existing saves will be lost.
Implemented part selection duplication. To duplicate the currently selected parts, click Duplicate Selected in the SELECTION menu, or press Left Ctrl + D.
Torsion springs now have an option to turn off angle clamping.
Engine "front crank" parts are now deprecated and hidden in the spawner UI (given that the "crank nose" part makes them redundant).
Modified the EngineTool script mod to allow choice between showing engine head's timing angle or current crank angle.
Lua scripting:-
Added Physics module with methods for raycasts, spherecasts, etc.
Added PartColliderRegistry, with a method for retrieving a part from the ID of one of its colliders.
Added an overload of CreateAttachment() in IAttachmentOperations that takes a separate search position and normal for the owner and connected parts.
Typing "LogKeyNames" or "LogAxisNames" in the debug console now lists all available input key and axis names respectively (to be used in Input.GetKey() etc. for Lua scripting).
Added "Concrete Pad" map.
Bug fixes.
1 note
·
View note
Text
CAS creativity November
I also work on the game, initiating the creation of the tiles by the map. This portion was rather challenging, as the development and implementation of a functional tile system took a lot of planning and debugging. I had to consider factors like tile placement, smooth transitions, and how the grid interplays with the game mechanics.
Before I dove into the code, I spent some time designing different lay-outs of the tiles and contemplating the best structure to use in organizing the map. I researched different approaches to tile-mapping to see whether a static grid or dynamic solution would be implemented. The initial iteration was tough to code, and while I did a great job with it, there's a lot of clean-up that needs to happen. I need to optimize performance, ensure smooth rendering, and possibly add different tile variations to enhance the game’s visual appeal. There’s still much to do, but I’m excited to see how the map evolves and how it will shape the overall gameplay experience. My next steps will involve fine-tuning the tile interactions, adding textures, and testing different configurations to make the map feel more dynamic and engaging.
private void OnDrawGizmos() { for (int z = 0; z < Height; z++) { for (int x = 0; x < Width; x++) { // Calculate the center position of each hex Vector3 centrePosition = HexMetrics.Center(HexSize, x, z, Orientation) + transform.position; // Draw the hexagon's edges Vector3[] corners = HexMetrics.Corners(HexSize, Orientation); for (int s = 0; s < corners.Length; s++) { Gizmos.DrawLine( centrePosition + corners[s], centrePosition + corners[(s + 1) % corners.Length] ); } } } }
0 notes
Text
Dev Day One
My plans for today are fairly short, I want to:
make the player move
get the resolution correct
---
So first off I make the movement for the player, which looks like this:
Basically when the player uses the W or S key, it'll set vertical to either 1 or -1 (same goes with A and D for the horizontal value). Then I'm setting the velocity of the player to be the movement speed * the combination of the keys as a vector3 (y is set to 0 as I don't want the player travelling upwards).
Now for the resolution, like the movement I have done this before... but I partially forgot how to do it. I made a new render texture, set the filter mode to point and the size to 100 x 100.
Then I made a raw image and set the texture to my render texture.
It was at this point I got a little stuck and pondered on what step I was missing. After a bit of experimenting I figured out that I had to set the render texture of the camera to my render texture.
This is what 100x100 looks like:
It's got the low quality look, but a bit too low quality... Also the image is stretched as it is 100x100 on a 1080x720 resolution.
This is what it looks like at 180x120:
The reason I made it 180x120 is because the resolution can be simplified from 1080 x 720 down to a ratio of 3:2. So I multiplied this ratio by 60 to get 180x120, which as you can see is no longer stretched. Although it may be still too low quality.
I did some tests with some higher qualities although they mostly looked the same, I ended up settling on 270x180:
This is what objects will look like up close:
Now that I have the average indie game camera quality sorted out, it would be time for the camera movement, however I also forgot how to do that. So putting that off for now I want to block out the design for my level just to get a feel for the scale of everything.
For the size of the level I feel like this should suffice for now:
I'm thinking of having the shelves be this large (remember there will be like 8 of these down one side of an aisle):
This is it looks with the walls:
So I lost a fair bit of blogging today as the internet had gone out (I'm lucky that I didn't lose all of this). Although most of it was just boxing out the level and improving the movement.
Here's what the level looks like now:
I also updated the movement script to so that whatever way the player is facing is forwards (movement is based on local rotation not global).
0 notes
Text
I can’t try it as quaternions bcs the RotationOffset is already a Vector3. However since the .y and .z parts are fine (there should never be yz asymmetry or roll in your hips through head chain), I can just set those as 0, which at least makes the line fit on the screen.
So now I need to look up how the rotation offset is calculated (difficult) or just try things (probably won’t work).
1 note
·
View note
Text
presenting another nifty little Unity script asset by ME! This Easy Object Pool system will get you spawning prefabs quickly using scriptable objects. I use it in my project for repetitive effects, requires very little setup beyond creating the scriptable objects & assigning them to the pool for runtime creation; great for prototyping. You can request objects spawn at a Vector3 position, or if you send a Transform, the object will take on the forward direction of the Transform, making it ideal for projectiles. You can also request varying sizes for the spawned objects and include xyz position offsets. Code is commented to be informative on its functions & invites customizability. and its free! wowie!!
#my assets#gamedev#indiedev#solodev#made with unity#unity assets#itch#itchio#code snippets#tutorial#coding help#nifty scripts#unity development
1 note
·
View note
Text
Cube UV
We are working on UV unwrapping in maya and photoshop. We got a cube in maya and opened the UV editor. We saved the UV version of the cube and saved it to open in photoshop.
We shaded the area around the cube black and drew some random symbols on it so that each face had something.
After that, we went back into maya and changed the material of the cube to lambert and imported the photoshop picture onto the cube. We did this by selecting the chekered box next to colour, file, and selecting the photoshop image, and then pressing the checkered circle on the hotbar above the cube to reveal the picture that we put on it.
We then imported the cube into unreal engine and selected the material of the cube to edit it. We separated the texture sample and lambert2 nodes and put in two vector3 nodes and a lerp. We changed the colours on each of the vector3's using the XYZ axis and connected them to lerp, which was then connected back to the lambert2 node.
In order to make the outlines glow, however, we got rid of the lerp and plugged the vector3 with the background colour we wanted into the lambert2. Then with the other vector3 and the texture sample, we connected them to a multiply node, which we then connected to another multiply node that was connected to the Emissive Colour pin to make the squiggles on my cube glow.
0 notes