Squashed commit of the following:

commit 5b888fba95
Author: AsanoRema <asanorema2036@gmail.com>
Date:   Tue Aug 11 10:30:09 2026 +0300

    Changed .gitignore

commit e3d5561fc8
Author: henjkey <henjkey@gmail.com>
Date:   Tue Aug 11 10:47:35 2026 +0500

    New

    Второй спавнер с нормальными настройками и обновленные префабы
This commit is contained in:
2026-08-11 10:47:50 +03:00
parent 6f296f91c3
commit 68ef673342
21 changed files with 1135 additions and 340 deletions
@@ -0,0 +1,176 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class ItemPipe : MonoBehaviour
{
[Serializable]
private class GuaranteedItem
{
public GameObject prefab;
[Min(1)]
public int amount = 1;
}
[Serializable]
private class RandomItem
{
public GameObject prefab;
[Min(0)]
public float weight = 1f;
}
[Header("Pipe")]
[SerializeField] private Transform spawnPoint;
[SerializeField, Min(0.05f)] private float spawnInterval = 0.5f;
[Header("Instant velocity change")]
[SerializeField] private Vector3 localVelocityChange = Vector3.forward * 4.5f;
[Header("Guaranteed items")]
[SerializeField] private List<GuaranteedItem> guaranteedItems = new();
[Header("Random items")]
[SerializeField, Min(0)] private int randomItemCount = 5;
[SerializeField] private List<RandomItem> randomItems = new();
[Header("Spawn position randomization")]
[SerializeField, Min(0f)] private float randomSpawnX = 0.2f;
[SerializeField, Min(0f)] private float randomSpawnZ = 0.2f;
[Header("Temporary testing")]
[SerializeField] private bool spawnOnE = true;
private bool isSpawning;
private void Update()
{
if (!spawnOnE || isSpawning || Keyboard.current == null)
return;
if (Keyboard.current.eKey.wasPressedThisFrame)
StartCoroutine(SpawnSequence());
}
private IEnumerator SpawnSequence()
{
isSpawning = true;
List<GameObject> spawnQueue = BuildSpawnQueue();
foreach (GameObject prefab in spawnQueue)
{
Spawn(prefab);
yield return new WaitForSeconds(spawnInterval);
}
isSpawning = false;
}
private List<GameObject> BuildSpawnQueue()
{
List<GameObject> queue = new();
// Добавляем предметы в точном количестве.
foreach (GuaranteedItem item in guaranteedItems)
{
if (item.prefab == null)
continue;
for (int i = 0; i < item.amount; i++)
queue.Add(item.prefab);
}
// Выбираем указанное количество случайных предметов.
for (int i = 0; i < randomItemCount; i++)
{
GameObject selectedPrefab = ChooseWeightedRandom();
if (selectedPrefab != null)
queue.Add(selectedPrefab);
}
// Перемешиваем гарантированные и случайные предметы вместе.
Shuffle(queue);
return queue;
}
private GameObject ChooseWeightedRandom()
{
float totalWeight = 0f;
foreach (RandomItem item in randomItems)
{
if (item.prefab != null && item.weight > 0f)
totalWeight += item.weight;
}
if (totalWeight <= 0f)
return null;
float roll = UnityEngine.Random.value * totalWeight;
float currentWeight = 0f;
foreach (RandomItem item in randomItems)
{
if (item.prefab == null || item.weight <= 0f)
continue;
currentWeight += item.weight;
if (roll < currentWeight)
return item.prefab;
}
return null;
}
private void Shuffle(List<GameObject> queue)
{
for (int i = queue.Count - 1; i > 0; i--)
{
int randomIndex = UnityEngine.Random.Range(0, i + 1);
(queue[i], queue[randomIndex]) =
(queue[randomIndex], queue[i]);
}
}
private void Spawn(GameObject prefab)
{
if (prefab == null || spawnPoint == null)
return;
float offsetX = RandomRange(-randomSpawnX, randomSpawnX);
float offsetZ = RandomRange(-randomSpawnZ, randomSpawnZ);
Vector3 spawnPosition =
spawnPoint.position +
spawnPoint.right * offsetX +
spawnPoint.forward * offsetZ;
GameObject item = Instantiate(
prefab,
spawnPosition,
UnityEngine.Random.rotationUniform
);
if (item.TryGetComponent(out Rigidbody body))
{
Vector3 worldVelocityChange =
spawnPoint.TransformDirection(localVelocityChange);
body.AddForce(worldVelocityChange, ForceMode.VelocityChange);
}
}
private float RandomRange(float min, float max)
{
return UnityEngine.Random.Range(min, max);
}
}