first commit
This commit is contained in:
14
Assets/Scripts/ScaleTest/Ball.physicMaterial
Normal file
14
Assets/Scripts/ScaleTest/Ball.physicMaterial
Normal file
@@ -0,0 +1,14 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!134 &13400000
|
||||
PhysicMaterial:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Ball
|
||||
dynamicFriction: 0.6
|
||||
staticFriction: 0.6
|
||||
bounciness: 0
|
||||
frictionCombine: 3
|
||||
bounceCombine: 1
|
||||
8
Assets/Scripts/ScaleTest/Ball.physicMaterial.meta
Normal file
8
Assets/Scripts/ScaleTest/Ball.physicMaterial.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e3e49e7b8690b24f8e060e1f8f3f2b8
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 13400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
14
Assets/Scripts/ScaleTest/CursorCustom.cs
Normal file
14
Assets/Scripts/ScaleTest/CursorCustom.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class CursorCustom : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Texture2D _cursorTexture;
|
||||
[SerializeField] private Vector2 _hotspot = Vector2.zero;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Cursor.SetCursor(_cursorTexture, _hotspot, CursorMode.Auto);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ScaleTest/CursorCustom.cs.meta
Normal file
11
Assets/Scripts/ScaleTest/CursorCustom.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea6af50377e1dac498dd8c9337abf6bf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
146
Assets/Scripts/ScaleTest/DraggableObject.cs
Normal file
146
Assets/Scripts/ScaleTest/DraggableObject.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DraggableObject : MonoBehaviour
|
||||
{
|
||||
[HideInInspector] public float mass = 1f;
|
||||
[HideInInspector] public bool isHeavy = false;
|
||||
[HideInInspector] public Transform priorityTarget = null;
|
||||
|
||||
public Vector3 startPosition { get; private set; }
|
||||
public Quaternion startRotation { get; private set; }
|
||||
|
||||
private Vector3 _mousePosition;
|
||||
private Vector3 _mouseCameraPos;
|
||||
private Vector3 _initialPosition;
|
||||
private Rigidbody _rb;
|
||||
private Camera _camera;
|
||||
private Transform _scaleTarget;
|
||||
private float _lerpPosition;
|
||||
[HideInInspector] public bool isDragging;
|
||||
|
||||
[SerializeField] private float _minY = 0.2f;
|
||||
[SerializeField] private float _maxDistanceFromStart = 30f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rb = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_camera = Camera.main;
|
||||
_rb.isKinematic = true;
|
||||
startPosition = transform.position;
|
||||
startRotation = transform.rotation;
|
||||
}
|
||||
|
||||
private Vector3 GetMousePos()
|
||||
{
|
||||
return _camera != null ? _camera.WorldToScreenPoint(transform.position) : Vector3.zero;
|
||||
}
|
||||
|
||||
private Transform GetNearestTargetToCursor()
|
||||
{
|
||||
if (priorityTarget != null && priorityTarget.gameObject.activeInHierarchy)
|
||||
return priorityTarget;
|
||||
|
||||
var targets = new List<GameObject>();
|
||||
targets.AddRange(GameObject.FindGameObjectsWithTag("ScaleTarget"));
|
||||
targets.AddRange(GameObject.FindGameObjectsWithTag("MainScale"));
|
||||
|
||||
Transform nearest = null;
|
||||
float minDist = float.MaxValue;
|
||||
foreach (var t in targets)
|
||||
{
|
||||
Vector3 screenPos = _camera.WorldToScreenPoint(t.transform.position);
|
||||
float d = Vector2.Distance(
|
||||
new Vector2(Input.mousePosition.x, Input.mousePosition.y),
|
||||
new Vector2(screenPos.x, screenPos.y));
|
||||
if (d < minDist) { minDist = d; nearest = t.transform; }
|
||||
}
|
||||
return nearest;
|
||||
}
|
||||
|
||||
private void OnMouseDown()
|
||||
{
|
||||
_rb.isKinematic = false;
|
||||
_rb.useGravity = false;
|
||||
_rb.velocity = Vector3.zero;
|
||||
_scaleTarget = GetNearestTargetToCursor();
|
||||
_initialPosition = transform.position;
|
||||
_mousePosition = Input.mousePosition - GetMousePos();
|
||||
isDragging = true;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!isDragging || _camera == null) return;
|
||||
|
||||
_rb.angularVelocity = Vector3.zero;
|
||||
_mouseCameraPos = _camera.ScreenToWorldPoint(Input.mousePosition - _mousePosition);
|
||||
|
||||
float targetZ = _scaleTarget != null ? _scaleTarget.position.z : _initialPosition.z;
|
||||
_lerpPosition = _scaleTarget != null
|
||||
? Mathf.InverseLerp(_initialPosition.x, _scaleTarget.position.x, _mouseCameraPos.x)
|
||||
: 0f;
|
||||
|
||||
transform.position = new Vector3(
|
||||
_mouseCameraPos.x,
|
||||
Mathf.Max(_mouseCameraPos.y, _minY),
|
||||
Mathf.Lerp(_initialPosition.z, targetZ, _lerpPosition)
|
||||
);
|
||||
|
||||
if (Input.GetMouseButtonUp(0))
|
||||
{
|
||||
isDragging = false;
|
||||
_rb.useGravity = true;
|
||||
_rb.isKinematic = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (isDragging) return;
|
||||
if (Vector3.Distance(transform.position, startPosition) > _maxDistanceFromStart)
|
||||
ResetToStart();
|
||||
}
|
||||
|
||||
public void ResetToStart()
|
||||
{
|
||||
_rb.velocity = Vector3.zero;
|
||||
_rb.angularVelocity = Vector3.zero;
|
||||
_rb.isKinematic = true;
|
||||
transform.position = startPosition;
|
||||
transform.rotation = startRotation;
|
||||
isDragging = false;
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (isDragging) return;
|
||||
if (!other.CompareTag("ScalePan")) return;
|
||||
StartCoroutine(SnapToPan(other.transform));
|
||||
}
|
||||
|
||||
private IEnumerator SnapToPan(Transform pan)
|
||||
{
|
||||
_rb.isKinematic = true;
|
||||
_rb.useGravity = false;
|
||||
|
||||
Vector3 targetPos = pan.position + Vector3.up * 0.1f;
|
||||
float t = 0f;
|
||||
Vector3 startPos = transform.position;
|
||||
|
||||
while (t < 1f)
|
||||
{
|
||||
t += Time.deltaTime * 5f;
|
||||
transform.position = Vector3.Lerp(startPos, targetPos, t);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
_rb.isKinematic = false;
|
||||
_rb.useGravity = true;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ScaleTest/DraggableObject.cs.meta
Normal file
11
Assets/Scripts/ScaleTest/DraggableObject.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2355647c3dcd1024db76db0ee01add9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
112
Assets/Scripts/ScaleTest/MainScaleZone.cs
Normal file
112
Assets/Scripts/ScaleTest/MainScaleZone.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
public class MainScaleZone : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject _mainScaleObject;
|
||||
[SerializeField] private Collider _mainScaleTrigger;
|
||||
[SerializeField] private TextMeshProUGUI _resultText;
|
||||
[SerializeField] private float _showResultTime = 2f;
|
||||
private bool _isChecking = false;
|
||||
private bool _canCheck = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_mainScaleObject.SetActive(false);
|
||||
_resultText.gameObject.SetActive(false);
|
||||
SetTag(false);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(1))
|
||||
{
|
||||
if (_mainScaleObject.activeSelf)
|
||||
{
|
||||
_mainScaleObject.SetActive(false);
|
||||
SetTag(false);
|
||||
SetPriorityForAllBalls(null);
|
||||
_canCheck = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_mainScaleObject.SetActive(true);
|
||||
SetTag(true);
|
||||
SetPriorityForAllBalls(_mainScaleTrigger.transform);
|
||||
_canCheck = false;
|
||||
StartCoroutine(EnableCheckDelay());
|
||||
}
|
||||
}
|
||||
|
||||
if (!_mainScaleObject.activeSelf || _isChecking || !_canCheck) return;
|
||||
|
||||
Collider[] cols = Physics.OverlapSphere(
|
||||
_mainScaleTrigger.bounds.center,
|
||||
_mainScaleTrigger.bounds.extents.magnitude
|
||||
);
|
||||
foreach (var col in cols)
|
||||
{
|
||||
DraggableObject ball = col.GetComponent<DraggableObject>();
|
||||
if (ball == null) continue;
|
||||
if (ball.isDragging) continue;
|
||||
Rigidbody rb = col.GetComponent<Rigidbody>();
|
||||
if (rb != null && rb.velocity.magnitude > 0.1f) continue;
|
||||
_isChecking = true;
|
||||
SetTag(false);
|
||||
if (ball.isHeavy)
|
||||
StartCoroutine(ShowResultAndRestart("³ðíî!"));
|
||||
else
|
||||
StartCoroutine(ShowResultAndContinue("Ñïðîáóé ùå"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPriorityForAllBalls(Transform target)
|
||||
{
|
||||
DraggableObject[] balls = FindObjectsOfType<DraggableObject>();
|
||||
foreach (var ball in balls)
|
||||
ball.priorityTarget = target;
|
||||
}
|
||||
|
||||
private IEnumerator EnableCheckDelay()
|
||||
{
|
||||
yield return new WaitForSeconds(2f);
|
||||
_canCheck = true;
|
||||
}
|
||||
|
||||
private IEnumerator ShowResultAndRestart(string text)
|
||||
{
|
||||
NewScaleZone scaleZone = FindObjectOfType<NewScaleZone>();
|
||||
scaleZone?.ShowSuccess();
|
||||
_resultText.text = text;
|
||||
_resultText.gameObject.SetActive(true);
|
||||
yield return new WaitForSeconds(_showResultTime);
|
||||
_mainScaleObject.SetActive(false);
|
||||
_resultText.gameObject.SetActive(false);
|
||||
SetPriorityForAllBalls(null);
|
||||
FindObjectOfType<WeighingManager>()?.FullRestart();
|
||||
scaleZone?.RestartAttempts();
|
||||
_isChecking = false;
|
||||
}
|
||||
|
||||
private IEnumerator ShowResultAndContinue(string text)
|
||||
{
|
||||
_resultText.text = text;
|
||||
_resultText.gameObject.SetActive(true);
|
||||
yield return new WaitForSeconds(_showResultTime);
|
||||
_mainScaleObject.SetActive(false);
|
||||
_resultText.gameObject.SetActive(false);
|
||||
SetPriorityForAllBalls(null);
|
||||
FindObjectOfType<WeighingManager>()?.ResetAllBalls();
|
||||
FindObjectOfType<NewScaleZone>()?.RegisterAttempt();
|
||||
_isChecking = false;
|
||||
}
|
||||
|
||||
private void SetTag(bool active)
|
||||
{
|
||||
if (_mainScaleTrigger != null)
|
||||
_mainScaleTrigger.gameObject.tag = active ? "MainScale" : "Untagged";
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ScaleTest/MainScaleZone.cs.meta
Normal file
11
Assets/Scripts/ScaleTest/MainScaleZone.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0da993b310702744097f97f6222567ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
161
Assets/Scripts/ScaleTest/NewScaleZone.cs
Normal file
161
Assets/Scripts/ScaleTest/NewScaleZone.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class NewScaleZone : MonoBehaviour
|
||||
{
|
||||
[Header("Scale Parts")]
|
||||
[SerializeField] private Transform _chainsOriginLeft;
|
||||
[SerializeField] private Transform _chainsOriginRight;
|
||||
[SerializeField] private Transform _beam;
|
||||
|
||||
[Header("Zones")]
|
||||
[SerializeField] private Collider _leftZoneCollider;
|
||||
[SerializeField] private Collider _rightZoneCollider;
|
||||
|
||||
[Header("Button")]
|
||||
[SerializeField] private Button _startButton;
|
||||
[SerializeField] private Sprite _spriteStart;
|
||||
[SerializeField] private Sprite _spriteInProgress;
|
||||
|
||||
[Header("UI")]
|
||||
[SerializeField] private TMPro.TextMeshProUGUI _attemptText;
|
||||
|
||||
[Header("Settings")]
|
||||
[SerializeField] private float _tiltSpeed = 1f;
|
||||
[SerializeField] private float _maxTiltAngle = 15f;
|
||||
[SerializeField] private float _maxChainOffset = 0.2f;
|
||||
[SerializeField] private float _showResultTime = 1.5f;
|
||||
|
||||
private int _attempt = 1;
|
||||
private Vector3 _beamStartRot;
|
||||
private Vector3 _leftChainStartPos;
|
||||
private Vector3 _rightChainStartPos;
|
||||
private bool _isWeighing = false;
|
||||
public int Attempt => _attempt;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_beamStartRot = _beam.localEulerAngles;
|
||||
_leftChainStartPos = _chainsOriginLeft.localPosition;
|
||||
_rightChainStartPos = _chainsOriginRight.localPosition;
|
||||
_startButton.onClick.AddListener(OnStartPressed);
|
||||
UpdateAttemptText();
|
||||
}
|
||||
|
||||
private float GetMassInZone(Collider zone)
|
||||
{
|
||||
Collider[] colliders = Physics.OverlapBox(
|
||||
zone.bounds.center,
|
||||
zone.bounds.extents,
|
||||
Quaternion.identity
|
||||
);
|
||||
float total = 0f;
|
||||
foreach (var col in colliders)
|
||||
{
|
||||
if (col.gameObject == zone.gameObject) continue;
|
||||
Rigidbody rb = col.GetComponent<Rigidbody>();
|
||||
if (rb != null) total += rb.mass;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
private void OnStartPressed()
|
||||
{
|
||||
if (_isWeighing) return;
|
||||
StartCoroutine(WeighRoutine());
|
||||
}
|
||||
|
||||
private IEnumerator WeighRoutine()
|
||||
{
|
||||
_isWeighing = true;
|
||||
_startButton.image.sprite = _spriteInProgress;
|
||||
|
||||
float leftMass = GetMassInZone(_leftZoneCollider);
|
||||
float rightMass = GetMassInZone(_rightZoneCollider);
|
||||
float diff = rightMass - leftMass;
|
||||
float normalized = Mathf.Clamp(diff / 2f, -1f, 1f);
|
||||
float targetAngle = -normalized * _maxTiltAngle;
|
||||
|
||||
float elapsed = 0f;
|
||||
float duration = 1.5f;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime * _tiltSpeed;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
|
||||
float angle = Mathf.Lerp(0f, targetAngle, t);
|
||||
_beam.localEulerAngles = new Vector3(
|
||||
_beamStartRot.x, _beamStartRot.y, _beamStartRot.z + angle);
|
||||
|
||||
float offset = normalized * _maxChainOffset * t;
|
||||
_chainsOriginLeft.localPosition = new Vector3(
|
||||
_leftChainStartPos.x, _leftChainStartPos.y - offset, _leftChainStartPos.z);
|
||||
_chainsOriginRight.localPosition = new Vector3(
|
||||
_rightChainStartPos.x, _rightChainStartPos.y + offset, _rightChainStartPos.z);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(_showResultTime);
|
||||
|
||||
elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime * _tiltSpeed;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
|
||||
float angle = Mathf.Lerp(targetAngle, 0f, t);
|
||||
_beam.localEulerAngles = new Vector3(
|
||||
_beamStartRot.x, _beamStartRot.y, _beamStartRot.z + angle);
|
||||
|
||||
float offset = normalized * _maxChainOffset * (1f - t);
|
||||
_chainsOriginLeft.localPosition = new Vector3(
|
||||
_leftChainStartPos.x, _leftChainStartPos.y - offset, _leftChainStartPos.z);
|
||||
_chainsOriginRight.localPosition = new Vector3(
|
||||
_rightChainStartPos.x, _rightChainStartPos.y + offset, _rightChainStartPos.z);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
_beam.localEulerAngles = _beamStartRot;
|
||||
_chainsOriginLeft.localPosition = _leftChainStartPos;
|
||||
_chainsOriginRight.localPosition = _rightChainStartPos;
|
||||
|
||||
WeighingManager manager = FindObjectOfType<WeighingManager>();
|
||||
if (manager != null) manager.ResetAllBalls();
|
||||
|
||||
_attempt++;
|
||||
UpdateAttemptText();
|
||||
_startButton.image.sprite = _spriteStart;
|
||||
_isWeighing = false;
|
||||
}
|
||||
|
||||
private void UpdateAttemptText()
|
||||
{
|
||||
if (_attemptText != null)
|
||||
_attemptText.text = "Ñïðîáà " + _attempt;
|
||||
}
|
||||
|
||||
public void ShowSuccess()
|
||||
{
|
||||
int count = _attempt <= 1 ? 1 : _attempt - 1;
|
||||
if (_attemptText != null)
|
||||
_attemptText.text = "Ïðîéäåíî ç " + count + " ñïðîá!";
|
||||
}
|
||||
|
||||
public void RegisterAttempt()
|
||||
{
|
||||
if (_isWeighing) return;
|
||||
_attempt++;
|
||||
UpdateAttemptText();
|
||||
}
|
||||
|
||||
public void RestartAttempts()
|
||||
{
|
||||
_attempt = 1;
|
||||
UpdateAttemptText();
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ScaleTest/NewScaleZone.cs.meta
Normal file
11
Assets/Scripts/ScaleTest/NewScaleZone.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dda24731fdf5b242b6dcd09c60a7e1a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Assets/Scripts/ScaleTest/WeighingManager.cs
Normal file
42
Assets/Scripts/ScaleTest/WeighingManager.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class WeighingManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private DraggableObject[] _balls;
|
||||
[SerializeField] private float _normalMass = 1f;
|
||||
[SerializeField] private float _heavyMass = 1.5f;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
AssignMasses();
|
||||
}
|
||||
|
||||
public void AssignMasses()
|
||||
{
|
||||
foreach (var ball in _balls)
|
||||
{
|
||||
ball.mass = _normalMass;
|
||||
ball.isHeavy = false;
|
||||
ball.GetComponent<Rigidbody>().mass = _normalMass;
|
||||
}
|
||||
int heavyIndex = Random.Range(0, _balls.Length);
|
||||
_balls[heavyIndex].mass = _heavyMass;
|
||||
_balls[heavyIndex].isHeavy = true;
|
||||
_balls[heavyIndex].GetComponent<Rigidbody>().mass = _heavyMass;
|
||||
}
|
||||
|
||||
public void ResetAllBalls()
|
||||
{
|
||||
foreach (var ball in _balls)
|
||||
ball.ResetToStart();
|
||||
}
|
||||
|
||||
public void FullRestart()
|
||||
{
|
||||
foreach (var ball in _balls)
|
||||
ball.ResetToStart();
|
||||
AssignMasses();
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ScaleTest/WeighingManager.cs.meta
Normal file
11
Assets/Scripts/ScaleTest/WeighingManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61ea5660dd2544b4fbe62b90469e654e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user