445 lines
15 KiB
C#
445 lines
15 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
public class SlidingObject : MonoBehaviour
|
||
{
|
||
[SerializeField] private ObjectInfoDisplay _display;
|
||
private Rigidbody _rb;
|
||
private string _currentSurface = "";
|
||
private bool _isMoving = false;
|
||
private bool _shownStatic = false;
|
||
private bool _wasOnShelf = false;
|
||
private bool _didSlide = false;
|
||
private string _lastShownName = "";
|
||
private float _lastMu = 0f;
|
||
private FrictionType _lastFrictionType;
|
||
private static readonly Dictionary<string, Dictionary<string, (float stat, float slide, float roll)>> _mu = new()
|
||
{
|
||
{
|
||
"Мармур",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Металева поверхня", (0.40f, 0.28f, -1) },
|
||
{ "Крижана поверхня", (0.10f, 0.06f, -1) },
|
||
{ "Гумова поверхня", (0.80f, 0.60f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Ядро",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.49f, 0.32f, 0.10f) },
|
||
{ "Металева поверхня", (0.23f, 0.15f, 0.08f) },
|
||
{ "Крижана поверхня", (0.05f, 0.03f, 0.02f) },
|
||
{ "Гумова поверхня", (0.65f, 0.50f, 0.15f) }
|
||
}
|
||
},
|
||
{
|
||
"Колесо гармати",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.49f, 0.32f, 0.05f) },
|
||
{ "Металева поверхня", (0.23f, 0.15f, 0.04f) },
|
||
{ "Крижана поверхня", (0.08f, 0.05f, 0.01f) },
|
||
{ "Гумова поверхня", (0.75f, 0.58f, 0.08f) }
|
||
}
|
||
},
|
||
{
|
||
"Надутий футбольний м'яч",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.65f, 0.50f, 0.04f) },
|
||
{ "Металева поверхня", (0.50f, 0.38f, 0.03f) },
|
||
{ "Крижана поверхня", (0.10f, 0.07f, 0.015f) },
|
||
{ "Гумова поверхня", (0.90f, 0.75f, 0.07f) }
|
||
}
|
||
},
|
||
{
|
||
"Здутий футбольний м'яч",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.80f, 0.65f, 0.09f) },
|
||
{ "Металева поверхня", (0.65f, 0.50f, 0.07f) },
|
||
{ "Крижана поверхня", (0.18f, 0.13f, 0.04f) },
|
||
{ "Гумова поверхня", (1.05f, 0.88f, 0.12f) }
|
||
}
|
||
},
|
||
{
|
||
"Гумова качечка",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.90f, 0.70f, -1) },
|
||
{ "Металева поверхня", (0.70f, 0.55f, -1) },
|
||
{ "Крижана поверхня", (0.20f, 0.15f, -1) },
|
||
{ "Гумова поверхня", (1.10f, 0.90f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Енциклопедія",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Металева поверхня", (0.35f, 0.25f, -1) },
|
||
{ "Крижана поверхня", (0.08f, 0.05f, -1) },
|
||
{ "Гумова поверхня", (0.80f, 0.65f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Авокадо",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.55f, 0.40f, -1) },
|
||
{ "Металева поверхня", (0.40f, 0.30f, -1) },
|
||
{ "Крижана поверхня", (0.10f, 0.07f, -1) },
|
||
{ "Гумова поверхня", (0.85f, 0.68f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Баскетбольний м'яч",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.70f, 0.55f, 0.05f) },
|
||
{ "Металева поверхня", (0.55f, 0.40f, 0.04f) },
|
||
{ "Крижана поверхня", (0.15f, 0.10f, 0.02f) },
|
||
{ "Гумова поверхня", (1.00f, 0.85f, 0.08f) }
|
||
}
|
||
},
|
||
{
|
||
"Стара шина",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.90f, 0.70f, 0.08f) },
|
||
{ "Металева поверхня", (0.70f, 0.55f, 0.06f) },
|
||
{ "Крижана поверхня", (0.18f, 0.12f, 0.02f) },
|
||
{ "Гумова поверхня", (1.10f, 0.90f, 0.10f) }
|
||
}
|
||
},
|
||
{
|
||
"Дерев'яна дошка",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.62f, 0.48f, -1) },
|
||
{ "Металева поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Крижана поверхня", (0.08f, 0.05f, -1) },
|
||
{ "Гумова поверхня", (0.75f, 0.60f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Пластикова дошка",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.40f, 0.28f, -1) },
|
||
{ "Металева поверхня", (0.35f, 0.25f, -1) },
|
||
{ "Крижана поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Гумова поверхня", (0.68f, 0.52f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Сніжок",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.15f, 0.10f, -1) },
|
||
{ "Металева поверхня", (0.10f, 0.07f, -1) },
|
||
{ "Крижана поверхня", (0.05f, 0.03f, -1) },
|
||
{ "Гумова поверхня", (0.35f, 0.25f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Лід",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.08f, 0.05f, -1) },
|
||
{ "Металева поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Крижана поверхня", (0.03f, 0.02f, -1) },
|
||
{ "Гумова поверхня", (0.25f, 0.18f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Скло",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.35f, 0.25f, -1) },
|
||
{ "Металева поверхня", (0.56f, 0.40f, -1) },
|
||
{ "Крижана поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Гумова поверхня", (0.70f, 0.55f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Монета",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.44f, 0.30f, 0.05f) },
|
||
{ "Металева поверхня", (0.57f, 0.44f, 0.04f) },
|
||
{ "Крижана поверхня", (0.05f, 0.03f, 0.01f) },
|
||
{ "Гумова поверхня", (0.65f, 0.50f, 0.08f) }
|
||
}
|
||
},
|
||
{
|
||
"Сталь",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Металева поверхня", (0.74f, 0.57f, -1) },
|
||
{ "Крижана поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Гумова поверхня", (0.65f, 0.50f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Мідь",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.50f, 0.36f, -1) },
|
||
{ "Металева поверхня", (0.53f, 0.36f, -1) },
|
||
{ "Крижана поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Гумова поверхня", (0.70f, 0.55f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Алюміній",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Металева поверхня", (0.61f, 0.47f, -1) },
|
||
{ "Крижана поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Гумова поверхня", (0.65f, 0.50f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Чавун",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.49f, 0.35f, -1) },
|
||
{ "Металева поверхня", (0.23f, 0.15f, -1) },
|
||
{ "Крижана поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Гумова поверхня", (0.70f, 0.55f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Ножиці",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Металева поверхня", (0.74f, 0.57f, -1) },
|
||
{ "Крижана поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Гумова поверхня", (0.65f, 0.50f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Скальпель",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.40f, 0.28f, -1) },
|
||
{ "Металева поверхня", (0.74f, 0.57f, -1) },
|
||
{ "Крижана поверхня", (0.05f, 0.03f, -1) },
|
||
{ "Гумова поверхня", (0.60f, 0.45f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Лічі",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.55f, 0.40f, -1) },
|
||
{ "Металева поверхня", (0.40f, 0.30f, -1) },
|
||
{ "Крижана поверхня", (0.08f, 0.06f, -1) },
|
||
{ "Гумова поверхня", (0.80f, 0.65f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Гумовий м'яч",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.90f, 0.70f, 0.05f) },
|
||
{ "Металева поверхня", (0.70f, 0.55f, 0.04f) },
|
||
{ "Крижана поверхня", (0.18f, 0.12f, 0.02f) },
|
||
{ "Гумова поверхня", (1.10f, 0.90f, 0.08f) }
|
||
}
|
||
},
|
||
{
|
||
"Асфальт",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.62f, 0.48f, -1) },
|
||
{ "Металева поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Крижана поверхня", (0.15f, 0.10f, -1) },
|
||
{ "Гумова поверхня", (0.90f, 0.75f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Каміння з мохом",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.55f, 0.40f, -1) },
|
||
{ "Металева поверхня", (0.45f, 0.33f, -1) },
|
||
{ "Крижана поверхня", (0.12f, 0.08f, -1) },
|
||
{ "Гумова поверхня", (0.80f, 0.65f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Цегла",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.62f, 0.48f, -1) },
|
||
{ "Металева поверхня", (0.50f, 0.36f, -1) },
|
||
{ "Крижана поверхня", (0.12f, 0.08f, -1) },
|
||
{ "Гумова поверхня", (0.85f, 0.70f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Скляна банка",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.35f, 0.25f, -1) },
|
||
{ "Металева поверхня", (0.56f, 0.40f, -1) },
|
||
{ "Крижана поверхня", (0.06f, 0.04f, -1) },
|
||
{ "Гумова поверхня", (0.68f, 0.52f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Лоток",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Металева поверхня", (0.74f, 0.57f, -1) },
|
||
{ "Крижана поверхня", (0.05f, 0.03f, -1) },
|
||
{ "Гумова поверхня", (0.60f, 0.45f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Блокнот",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.50f, 0.35f, -1) },
|
||
{ "Металева поверхня", (0.35f, 0.25f, -1) },
|
||
{ "Крижана поверхня", (0.08f, 0.05f, -1) },
|
||
{ "Гумова поверхня", (0.75f, 0.58f, -1) }
|
||
}
|
||
},
|
||
{
|
||
"Хірургічна пилка",
|
||
new()
|
||
{
|
||
{ "Дерев'яна поверхня", (0.40f, 0.28f, -1) },
|
||
{ "Металева поверхня", (0.74f, 0.57f, -1) },
|
||
{ "Крижана поверхня", (0.05f, 0.03f, -1) },
|
||
{ "Гумова поверхня", (0.60f, 0.45f, -1) }
|
||
}
|
||
},
|
||
};
|
||
private void Awake()
|
||
{
|
||
_rb = GetComponent<Rigidbody>();
|
||
_didSlide = false;
|
||
}
|
||
private void OnCollisionEnter(Collision collision)
|
||
{
|
||
string surface = GetSurfaceName(collision.gameObject);
|
||
if (surface != "")
|
||
{
|
||
_wasOnShelf = true;
|
||
_currentSurface = surface;
|
||
_isMoving = false;
|
||
_shownStatic = false;
|
||
return;
|
||
}
|
||
if (collision.gameObject.CompareTag("Floor") && _wasOnShelf && _didSlide)
|
||
{
|
||
_wasOnShelf = false;
|
||
_didSlide = false;
|
||
float speed = _rb.velocity.magnitude;
|
||
ObjectName objName = GetComponent<ObjectName>();
|
||
string name = objName != null ? objName.ukrainianName : gameObject.name;
|
||
StartCoroutine(ShowFallAfterSlide(name, speed));
|
||
_currentSurface = "";
|
||
}
|
||
else if (collision.gameObject.CompareTag("Floor"))
|
||
{
|
||
_wasOnShelf = false;
|
||
_didSlide = false;
|
||
}
|
||
}
|
||
private void OnCollisionExit(Collision collision)
|
||
{
|
||
string surface = GetSurfaceName(collision.gameObject);
|
||
if (surface == "") return;
|
||
_currentSurface = "";
|
||
_isMoving = false;
|
||
_shownStatic = false;
|
||
}
|
||
private void Update()
|
||
{
|
||
if (_currentSurface == "" || _display == null || _rb == null) return;
|
||
ObjectName objName = GetComponent<ObjectName>();
|
||
if (objName == null) return;
|
||
string rawName = objName.ukrainianName;
|
||
string name = _mu.ContainsKey(rawName)
|
||
? rawName
|
||
: rawName.Contains("Енциклопедія") ? "Енциклопедія" : rawName;
|
||
if (!_mu.TryGetValue(name, out var surfaces)) return;
|
||
if (!surfaces.TryGetValue(_currentSurface, out var mu)) return;
|
||
bool movingNow = _rb.velocity.magnitude > 0.05f;
|
||
if (!movingNow && !_shownStatic)
|
||
{
|
||
_shownStatic = true;
|
||
_isMoving = false;
|
||
_lastShownName = name;
|
||
_lastMu = mu.stat;
|
||
_lastFrictionType = FrictionType.Статичне;
|
||
_display.ShowSlide(name, _currentSurface, mu.stat, FrictionType.Статичне);
|
||
}
|
||
else if (movingNow && !_isMoving)
|
||
{
|
||
_isMoving = true;
|
||
_shownStatic = false;
|
||
StartCoroutine(ShowAfterDelay(name, mu));
|
||
}
|
||
}
|
||
private IEnumerator ShowAfterDelay(string name, (float stat, float slide, float roll) mu)
|
||
{
|
||
yield return new WaitForSeconds(0.3f);
|
||
if (_rb == null || _currentSurface == "") yield break;
|
||
float linearSpeed = _rb.velocity.magnitude;
|
||
float angularSpeed = _rb.angularVelocity.magnitude;
|
||
bool isRolling = angularSpeed > 0.5f && linearSpeed > 0.05f;
|
||
float shownMu;
|
||
FrictionType shownType;
|
||
if (isRolling && mu.roll >= 0f)
|
||
{
|
||
shownMu = mu.roll;
|
||
shownType = FrictionType.Кочення;
|
||
}
|
||
else if (isRolling && mu.roll < 0f)
|
||
{
|
||
shownMu = mu.slide;
|
||
shownType = FrictionType.Кочення;
|
||
}
|
||
else
|
||
{
|
||
shownMu = mu.slide;
|
||
shownType = FrictionType.Ковзання;
|
||
}
|
||
if (_lastFrictionType == shownType && _lastMu == shownMu) yield break;
|
||
_lastShownName = name;
|
||
_lastMu = shownMu;
|
||
_lastFrictionType = shownType;
|
||
_didSlide = true;
|
||
_display.ShowSlide(name, _currentSurface, shownMu, shownType);
|
||
GameData.AddFriction(name, _currentSurface, shownMu, shownType);
|
||
}
|
||
private IEnumerator ShowFallAfterSlide(string name, float speed)
|
||
{
|
||
yield return new WaitForSeconds(_display.displayTime + _display.fadeTime);
|
||
_display.ShowFall(name, speed);
|
||
}
|
||
private string GetSurfaceName(GameObject obj)
|
||
{
|
||
ObjectName objName = obj.GetComponent<ObjectName>();
|
||
if (objName == null)
|
||
objName = obj.GetComponentInParent<ObjectName>();
|
||
if (objName != null)
|
||
return objName.description;
|
||
return "";
|
||
}
|
||
}
|