1
0
forked from cgvr/DeltaVR

ShapeScanner multiple configurations, configurable in editor

This commit is contained in:
2026-01-14 14:02:10 +02:00
parent 33a40c987a
commit 96839e0e82
9 changed files with 448 additions and 70 deletions

View File

@@ -27,8 +27,8 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1013838101896458198}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: -0.21589, z: 0}
m_LocalScale: {x: 0.64645, y: 0.029855646, z: 0.64645}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.6, y: 0.03, z: 0.6}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8294461198356057691}
@@ -105,6 +105,146 @@ BoxCollider:
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &1231701550042884109
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8594417542550664647}
- component: {fileID: 7869926060146003813}
- component: {fileID: 5476518908687164580}
m_Layer: 0
m_Name: CurrentConfigurationDisplay
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8594417542550664647
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1231701550042884109}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6932860525531626823}
m_RootOrder: -1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0}
m_AnchorMax: {x: 0.5, y: 0}
m_AnchoredPosition: {x: 0, y: 22.45}
m_SizeDelta: {x: 50, y: 14}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7869926060146003813
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1231701550042884109}
m_CullTransparentMesh: 1
--- !u!114 &5476518908687164580
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1231701550042884109}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: '0 / 2
'
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 254d33525bc3919439f569ea33703c5b, type: 2}
m_sharedMaterial: {fileID: 4369893532151414794, guid: 254d33525bc3919439f569ea33703c5b,
type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 12
m_fontSizeBase: 12
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &1374309978863673311
GameObject:
m_ObjectHideFlags: 0
@@ -129,7 +269,7 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1374309978863673311}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.3, y: 0, z: 0.3}
m_LocalPosition: {x: 0.275, y: 0, z: 0.275}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
@@ -160,7 +300,7 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1598434951760464124}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: -0.416, z: 0}
m_LocalPosition: {x: 0, y: -0.225, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
@@ -199,6 +339,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8594417542550664647}
- {fileID: 6492405423818451632}
m_Father: {fileID: 5335160954898573969}
m_RootOrder: -1
@@ -273,8 +414,8 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3769602036287398038}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: -0.61411, z: 0}
m_LocalScale: {x: 0.64645, y: 0.029855646, z: 0.64645}
m_LocalPosition: {x: 0, y: -0.5, z: 0}
m_LocalScale: {x: 0.6, y: 0.03, z: 0.6}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8294461198356057691}
@@ -375,7 +516,7 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5358414661713154358}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -0.3, y: 0, z: -0.3}
m_LocalPosition: {x: -0.275, y: 0, z: -0.275}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
@@ -394,7 +535,7 @@ GameObject:
- component: {fileID: 489185111762359262}
- component: {fileID: 7443612957244256760}
m_Layer: 0
m_Name: Text
m_Name: CorrectPercentageDisplay
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -415,9 +556,9 @@ RectTransform:
m_Father: {fileID: 6932860525531626823}
m_RootOrder: -1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_AnchorMin: {x: 0.5, y: 0}
m_AnchorMax: {x: 0.5, y: 0}
m_AnchoredPosition: {x: 0, y: 7}
m_SizeDelta: {x: 50, y: 14}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &489185111762359262
@@ -570,25 +711,38 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: b2226de466bbe814d8bfe0cb0fce83f6, type: 3}
m_Name:
m_EditorClassIdentifier:
configuration:
- cells: 010001010000
- cells: 000101010000
- cells: 010101010101
- cells: 000000000000
- cells: 000000000000
- cells: 000000000000
configurations:
- columns: 6
requiredCorrectPercentage: 80
rows:
- cells: 000000000000
- cells: 000001010000
- cells: 000001010000
- cells: 000101010100
- cells: 010101010101
- cells: 000000000000
- columns: 6
requiredCorrectPercentage: 80
rows:
- cells: 000001000000
- cells: 000101010100
- cells: 000101010101
- cells: 010101010100
- cells: 000101010100
- cells: 000000010000
rayPrefab: {fileID: 1303694035827653214, guid: dfe698ad960ffbd47a7d0ff8f6b5baa3,
type: 3}
raySpawnCorner1: {fileID: 4055409281532582849}
raySpawnCorner2: {fileID: 8025195334996356355}
rayParent: {fileID: 4362133469817120903}
currentConfigurationDisplay: {fileID: 5476518908687164580}
correctPercentageDisplay: {fileID: 7443612957244256760}
requiredAndActive: {fileID: 2100000, guid: dccb608b252977047bd5848d6a497bfb, type: 2}
requiredAndPassive: {fileID: 2100000, guid: c0707507abffb6149b19e60299403e82, type: 2}
notRequiredAndActive: {fileID: 2100000, guid: c7aad7ea05b9332478242744c9de52b9,
type: 2}
notRequiredAndPassive: {fileID: 2100000, guid: 991fa2870324ba04aba7bec9e1168afa,
type: 2}
displayText: {fileID: 7443612957244256760}
--- !u!54 &6146655625910388013
Rigidbody:
m_ObjectHideFlags: 0
@@ -707,7 +861,7 @@ MonoBehaviour:
m_Calls: []
m_AttachTransform: {fileID: 0}
m_SecondaryAttachTransform: {fileID: 0}
m_UseDynamicAttach: 0
m_UseDynamicAttach: 1
m_MatchAttachPosition: 1
m_MatchAttachRotation: 1
m_SnapToColliderVolume: 1
@@ -788,8 +942,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 50, y: 20}
m_AnchoredPosition: {x: 0, y: 0.16}
m_SizeDelta: {x: 50, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!223 &2825347825077556369
Canvas:

View File

@@ -29,11 +29,11 @@ Transform:
m_GameObject: {fileID: 8688612914795219519}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0.259, y: 0.012, z: -0.26886}
m_LocalScale: {x: 0.035900656, y: 0.45784503, z: 0.035900656}
m_LocalScale: {x: 0.035, y: 0.5, z: 0.035}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: -1
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8730629787356023745
MeshFilter:
@@ -118,5 +118,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: db942dc95bda5a149b7e9358de43a923, type: 3}
m_Name:
m_EditorClassIdentifier:
activeMaterial: {fileID: 0}
passiveMaterial: {fileID: 0}
_activeMaterial: {fileID: 0}
_passiveMaterial: {fileID: 0}
scannableTag: ShapeScannable

View File

@@ -12,6 +12,7 @@ public class MicrophoneStand : MonoBehaviour
private WhisperStream stream;
[SerializeField]
private string textOutput;
public GameObject microphoneOffStatus;

View File

@@ -76,6 +76,8 @@ public class ShapeDetectionMinigameController : MonoBehaviour
//spawnedObject.AddComponent<NetworkObject>();
//spawnedObject.AddComponent<NetworkTransform>();
MeshCollider spawnedObjectCollider = spawnedObject.GetComponent<MeshCollider>();
spawnedObjectCollider.convex = false;
spawnedObject.transform.parent = spawnedObjectParent.transform;
spawnedObject.transform.position = spawnedObjectParent.transform.position;
spawnedObject.tag = shapeScannerTag;

View File

@@ -1,68 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
[System.Serializable]
[Serializable]
public class BoolRow
{
public bool[] cells;
public List<bool> cells = new List<bool>();
}
[Serializable]
public class ShapeScannerConfiguration
{
public int columns = 6;
public float requiredCorrectPercentage = 80.0f;
public List<BoolRow> rows = new List<BoolRow>();
}
public class ShapeScanner : MonoBehaviour
{
public List<BoolRow> configuration;
public List<ShapeScannerConfiguration> configurations = new List<ShapeScannerConfiguration>();
public ShapeScannerRay rayPrefab;
public Transform raySpawnCorner1;
public Transform raySpawnCorner2;
public Transform rayParent;
public TextMeshProUGUI currentConfigurationDisplay;
public TextMeshProUGUI correctPercentageDisplay;
public Material requiredAndActive;
public Material requiredAndPassive;
public Material notRequiredAndActive;
public Material notRequiredAndPassive;
public TextMeshProUGUI displayText;
private List<GameObject> existingRays;
private float raySpawnDistanceX;
private float raySpawnDistanceZ;
private int currentConfiguration;
private int rayCount;
private int correctRayStates;
private void Awake()
{
correctRayStates = 0;
}
// Start is called before the first frame update
void Start()
{
float raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x;
float raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z;
existingRays = new List<GameObject>();
raySpawnDistanceX = raySpawnCorner2.localPosition.x - raySpawnCorner1.localPosition.x;
raySpawnDistanceZ = raySpawnCorner2.localPosition.z - raySpawnCorner1.localPosition.z;
int rayRowCount = configuration.Count;
for (int i = 0; i < rayRowCount; i++)
{
float rayPosX = raySpawnCorner1.localPosition.x + i * raySpawnDistanceX / (rayRowCount - 1);
for (int j = 0; j < rayRowCount; j++)
{
rayCount++;
// Local position
float rayPosZ = raySpawnCorner1.localPosition.z + j * raySpawnDistanceZ / (rayRowCount - 1);
Vector3 rayPos = new Vector3(rayPosX, 0, rayPosZ);
ShapeScannerRay ray = Instantiate(rayPrefab, rayParent);
ray.transform.localPosition = rayPos;
bool rayCollisionRequired = configuration[i].cells[j];
if (rayCollisionRequired)
{
ray.Initialize(this, rayCollisionRequired, requiredAndActive, requiredAndPassive);
} else
{
ray.Initialize(this, rayCollisionRequired, notRequiredAndActive, notRequiredAndPassive);
IncrementCorrectRayCount();
}
}
}
currentConfiguration = 0;
InitializeConfiguration();
}
// Update is called once per frame
@@ -71,21 +60,82 @@ public class ShapeScanner : MonoBehaviour
}
private void InitializeConfiguration()
{
// Delete all existing rays first
foreach (GameObject ray in existingRays)
{
Destroy(ray);
}
ShapeScannerConfiguration configuration = configurations[currentConfiguration];
int rayRowCount = configuration.rows.Count;
for (int i = 0; i < rayRowCount; i++)
{
float rayPosX = raySpawnCorner1.localPosition.x + i * raySpawnDistanceX / (rayRowCount - 1);
for (int j = 0; j < rayRowCount; j++)
{
// Local position
float rayPosZ = raySpawnCorner1.localPosition.z + j * raySpawnDistanceZ / (rayRowCount - 1);
Vector3 rayPos = new Vector3(rayPosX, 0, rayPosZ);
ShapeScannerRay ray = Instantiate(rayPrefab, rayParent);
ray.transform.localPosition = rayPos;
existingRays.Add(ray.gameObject);
bool rayCollisionRequired = configuration.rows[i].cells[j];
if (rayCollisionRequired)
{
ray.Initialize(this, rayCollisionRequired, requiredAndActive, requiredAndPassive);
}
else
{
ray.Initialize(this, rayCollisionRequired, notRequiredAndActive, notRequiredAndPassive);
}
}
}
// Count total rays and required collision rays
rayCount = configuration.rows.SelectMany(row => row.cells).Count();
correctRayStates = configuration.rows.SelectMany(row => row.cells).Count(cell => !cell);
UpdateDisplay(calculateCorrectPercentage());
}
private float calculateCorrectPercentage()
{
return Mathf.RoundToInt((float)correctRayStates / rayCount * 100);
}
public void IncrementCorrectRayCount()
{
correctRayStates++;
UpdateDisplay();
float correctPercentage = calculateCorrectPercentage();
if (correctPercentage >= configurations[currentConfiguration].requiredCorrectPercentage)
{
UpdateCurrentConfigurationDisplay(currentConfiguration + 1);
if (currentConfiguration + 1 < configurations.Count)
{
currentConfiguration++;
InitializeConfiguration();
} else
{
Debug.Log("Shape checker completed");
}
}
UpdateDisplay(correctPercentage);
}
public void DecrementCorrectRayCount()
{
correctRayStates--;
UpdateDisplay();
UpdateDisplay(calculateCorrectPercentage());
}
private void UpdateDisplay()
private void UpdateDisplay(float percentage)
{
int percentage = Mathf.RoundToInt((float) correctRayStates / rayCount * 100);
displayText.text = percentage.ToString() + " %";
correctPercentageDisplay.text = Mathf.Round(percentage).ToString() + " %";
}
private void UpdateCurrentConfigurationDisplay(int confNumber)
{
currentConfigurationDisplay.text = confNumber.ToString() + " / " + configurations.Count;
}
}