Skip to content

Commit 2c64952

Browse files
Add files via upload (#201)
1 parent 7416b8e commit 2c64952

File tree

4 files changed

+315
-35
lines changed

4 files changed

+315
-35
lines changed

src/bundles/unity_academy/UnityAcademy.tsx

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,7 @@ import React from 'react';
1010
import ReactDOM from 'react-dom';
1111
import { Button } from '@blueprintjs/core';
1212
import { IconNames } from '@blueprintjs/icons';
13-
14-
type Vector3 = {
15-
x : number;
16-
y : number;
17-
z : number;
18-
};
13+
import { Vector3, normalizeVector, zeroVector, pointDistance } from './UnityAcademyMaths';
1914

2015
type Transform = {
2116
position : Vector3;
@@ -48,7 +43,7 @@ type RigidbodyData = {
4843
angularDrag : number;
4944
};
5045

51-
declare const createUnityInstance : Function; // This function comes from Build.loader.js in Unity Academy Application
46+
declare const createUnityInstance : Function; // This function comes from {BUILD_NAME}.loader.js in Unity Academy Application (For Example: ua-frontend-prod.loader.js)
5247

5348
export function getInstance() : UnityAcademyJsInteropContext {
5449
return (window as any).unityAcademyContext as UnityAcademyJsInteropContext;
@@ -356,21 +351,9 @@ class UnityAcademyJsInteropContext {
356351
onCollisionStayMethod: null,
357352
onCollisionExitMethod: null,
358353
transform: {
359-
position: {
360-
x: 0,
361-
y: 0,
362-
z: 0,
363-
},
364-
rotation: {
365-
x: 0,
366-
y: 0,
367-
z: 0,
368-
},
369-
scale: {
370-
x: 1,
371-
y: 1,
372-
z: 1,
373-
},
354+
position: zeroVector(),
355+
rotation: zeroVector(),
356+
scale: new Vector3(1, 1, 1),
374357
},
375358
rigidbody: null,
376359
customProperties: {},
@@ -453,6 +436,21 @@ class UnityAcademyJsInteropContext {
453436
gameObject.transform.position.z += finalWorldTranslateVector[2];
454437
}
455438

439+
lookAtPositionInternal(gameObjectIdentifier : GameObjectIdentifier, x : number, y : number, z : number) : void {
440+
const gameObject = this.getStudentGameObject(gameObjectIdentifier);
441+
const deltaVector = normalizeVector(new Vector3(x - gameObject.transform.position.x, y - gameObject.transform.position.y, z - gameObject.transform.position.z));
442+
const eulerX = Math.asin(-deltaVector.y);
443+
const eulerY = Math.atan2(deltaVector.x, deltaVector.z);
444+
gameObject.transform.rotation.x = eulerX * 180 / Math.PI;
445+
gameObject.transform.rotation.y = eulerY * 180 / Math.PI;
446+
}
447+
448+
gameObjectDistanceInternal(gameObjectIdentifier_A : GameObjectIdentifier, gameObjectIdentifier_B : GameObjectIdentifier) : number {
449+
const gameObjectA = this.getStudentGameObject(gameObjectIdentifier_A);
450+
const gameObjectB = this.getStudentGameObject(gameObjectIdentifier_B);
451+
return pointDistance(gameObjectA.transform.position, gameObjectB.transform.position);
452+
}
453+
456454
rotateWorldInternal(gameObjectIdentifier : GameObjectIdentifier, x : number, y : number, z : number) : void {
457455
const gameObject = this.getStudentGameObject(gameObjectIdentifier);
458456
gameObject.transform.rotation.x += x;
@@ -484,16 +482,8 @@ class UnityAcademyJsInteropContext {
484482
throw new Error(`Trying to duplicately apply rigidbody on GameObject ${gameObjectIdentifier.gameObjectIdentifier}`);
485483
}
486484
gameObject.rigidbody = {
487-
velocity: {
488-
x: 0,
489-
y: 0,
490-
z: 0,
491-
},
492-
angularVelocity: {
493-
x: 0,
494-
y: 0,
495-
z: 0,
496-
},
485+
velocity: zeroVector(),
486+
angularVelocity: zeroVector(),
497487
mass: 1,
498488
useGravity: true,
499489
drag: 0,
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Maths functions for Source Academy's Unity Academy module
3+
* @module unity_academy
4+
* @author Wang Zihan
5+
*/
6+
7+
export class Vector3 {
8+
x = 0;
9+
y = 0;
10+
z = 0;
11+
constructor(x, y, z) {
12+
this.x = x;
13+
this.y = y;
14+
this.z = z;
15+
}
16+
17+
toString() {
18+
return `(${this.x}, ${this.y}, ${this.z})`;
19+
}
20+
}
21+
22+
export function checkVector3Parameter(parameter : any) : void {
23+
if (typeof (parameter) !== 'object') {
24+
throw new Error(`The given parameter is not a valid 3D vector! Wrong parameter type: ${typeof (parameter)}`);
25+
}
26+
if (typeof (parameter.x) !== 'number' || typeof (parameter.y) !== 'number' || typeof (parameter.z) !== 'number') {
27+
throw new Error('The given parameter is not a valid 3D vector!');
28+
}
29+
}
30+
31+
export function makeVector3D(x : number, y : number, z : number) : Vector3 {
32+
return new Vector3(x, y, z);
33+
}
34+
35+
export function scaleVector(vector : Vector3, factor : number) : Vector3 {
36+
return new Vector3(vector.x * factor, vector.y * factor, vector.z * factor);
37+
}
38+
39+
export function addVector(vectorA : Vector3, vectorB : Vector3) : Vector3 {
40+
return new Vector3(vectorA.x + vectorB.x, vectorA.y + vectorB.y, vectorA.z + vectorB.z);
41+
}
42+
43+
export function dotProduct(vectorA : Vector3, vectorB : Vector3) : number {
44+
return vectorA.x * vectorB.x + vectorA.y * vectorB.y + vectorA.z * vectorB.z;
45+
}
46+
47+
export function crossProduct(vectorA : Vector3, vectorB : Vector3) : Vector3 {
48+
return new Vector3(vectorA.y * vectorB.z - vectorB.y * vectorA.z, vectorB.x * vectorA.z - vectorA.x * vectorB.z, vectorA.x * vectorB.y - vectorB.x * vectorA.y);
49+
}
50+
51+
export function vectorMagnitude(vector : Vector3) : number {
52+
return Math.sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
53+
}
54+
55+
export function normalizeVector(vector : Vector3) : Vector3 {
56+
const magnitude = vectorMagnitude(vector);
57+
if (magnitude === 0) return new Vector3(0, 0, 0); // If the parameter is a zero vector, then return a new zero vector.
58+
return new Vector3(vector.x / magnitude, vector.y / magnitude, vector.z / magnitude);
59+
}
60+
61+
export function zeroVector() : Vector3 {
62+
return new Vector3(0, 0, 0);
63+
}
64+
65+
export function pointDistance(pointA : Vector3, pointB : Vector3) : number {
66+
return Math.sqrt((pointB.x - pointA.x) ** 2 + (pointB.y - pointA.y) ** 2 + (pointB.z - pointA.z) ** 2);
67+
}

src/bundles/unity_academy/functions.ts

Lines changed: 211 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66

77

88
import { initializeModule, getInstance, type GameObjectIdentifier } from './UnityAcademy';
9+
import {
10+
type Vector3, checkVector3Parameter, makeVector3D, scaleVector, addVector, dotProduct, crossProduct,
11+
normalizeVector, vectorMagnitude, zeroVector, pointDistance,
12+
} from './UnityAcademyMaths';
913

1014

1115
/**
12-
* Load and initialize Unity Academy WebGL player and set it to 2D mode. All other functions in this module requires calling this function or init_unity_academy_3d first.<br>
16+
* Load and initialize Unity Academy WebGL player and set it to 2D mode. All other functions (except Maths functions) in this module requires calling this function or init_unity_academy_3d first.<br>
1317
* I recommand you just call this function at the beginning of your Source Unity program under the 'import' statements.
1418
*
1519
* @category Application Initialization
@@ -20,7 +24,7 @@ export function init_unity_academy_2d() : void {
2024
}
2125

2226
/**
23-
* Load and initialize Unity Academy WebGL player and set it to 3D mode. All other functions in this module requires calling this function or init_unity_academy_2d first.<br>
27+
* Load and initialize Unity Academy WebGL player and set it to 3D mode. All other functions (except Maths functions) in this module requires calling this function or init_unity_academy_2d first.<br>
2428
* I recommand you just call this function at the beginning of your Source Unity program under the 'import' statements.
2529
*
2630
* @category Application Initialization
@@ -459,6 +463,49 @@ export function copy_scale(from : GameObjectIdentifier, to : GameObjectIdentifie
459463
.copyTransformPropertiesInternal('scale', from, to, delta_x, delta_y, delta_z);
460464
}
461465

466+
/**
467+
* Makes the GameObject "Look At" a given position.<br>
468+
* <b>3D mode only</b><br>
469+
* <br>
470+
* The +Z direction of the GameObject (which denotes forward in Unity's conventions) will pointing to the given position.<br>
471+
* <br>
472+
* For more information, see https://docs.unity3d.com/ScriptReference/Transform.LookAt.html<br>
473+
*
474+
* @param gameObjectIdentifier The identifier for the GameObject that you need to make it "look at" a position
475+
* @param x The X value of the "look at" position
476+
* @param y The Y value of the "look at" position
477+
* @param z The Z value of the "look at" position
478+
*
479+
* @category Transform
480+
*/
481+
export function look_at(gameObjectIdentifier : GameObjectIdentifier, x : number, y : number, z : number) : void {
482+
checkUnityAcademyExistence();
483+
checkIs3DMode();
484+
checkGameObjectIdentifierParameter(gameObjectIdentifier);
485+
checkParameterType(x, 'number');
486+
checkParameterType(y, 'number');
487+
checkParameterType(z, 'number');
488+
getInstance()
489+
.lookAtPositionInternal(gameObjectIdentifier, x, y, z);
490+
}
491+
492+
/**
493+
* Calcuate the distance between two GameObjects, based on each other's position
494+
* @param gameObjectIdentifier_A The identifier for the first GameObject
495+
* @param gameObjectIdentifier_B The identifier for the second GameObject
496+
*
497+
*
498+
* @return The value of the distance between these two GameObjects
499+
* @category Transform
500+
*/
501+
export function gameobject_distance(gameObjectIdentifier_A : GameObjectIdentifier, gameObjectIdentifier_B : GameObjectIdentifier) : number {
502+
checkUnityAcademyExistence();
503+
checkGameObjectIdentifierParameter(gameObjectIdentifier_A);
504+
checkGameObjectIdentifierParameter(gameObjectIdentifier_B);
505+
return getInstance()
506+
.gameObjectDistanceInternal(gameObjectIdentifier_A, gameObjectIdentifier_B);
507+
}
508+
462509
function checkKeyCodeValidityAndToLowerCase(keyCode : string) : string {
463510
if (typeof (keyCode) !== 'string') throw new Error(`Key code must be a string! Given type: ${typeof (keyCode)}`);
464511
if (keyCode === 'LeftMouseBtn' || keyCode === 'RightMouseBtn' || keyCode === 'MiddleMouseBtn' || keyCode === 'LeftShift' || keyCode === 'RightShift') return keyCode;
@@ -940,3 +987,165 @@ export function get_custom_prop(gameObjectIdentifier : GameObjectIdentifier, pro
940987
return getInstance()
941988
.getCustomPropertyInternal(gameObjectIdentifier, propName);
942989
}
990+
991+
/**
992+
* Create a 3D vector
993+
* @param x The x component of the new vector
994+
* @param y The y component of the new vector
995+
* @param z The z component of the new vector
996+
*
997+
* @return The 3D vector (x, y, z)
998+
*
999+
* @category Maths
1000+
*/
1001+
export function vector3(x : number, y : number, z : number) : Vector3 {
1002+
checkParameterType(x, 'number');
1003+
checkParameterType(y, 'number');
1004+
checkParameterType(z, 'number');
1005+
return makeVector3D(x, y, z);
1006+
}
1007+
1008+
/**
1009+
* Get the X component of a 3D vector
1010+
* @param vector The 3D vector
1011+
*
1012+
* @return The X component of the given vector
1013+
*
1014+
* @category Maths
1015+
*/
1016+
export function get_x(vector : Vector3) : number {
1017+
checkVector3Parameter(vector);
1018+
return vector.x;
1019+
}
1020+
1021+
/**
1022+
* Get the Y component of a 3D vector
1023+
* @param vector The 3D vector
1024+
*
1025+
* @return The Y component of the given vector
1026+
*
1027+
* @category Maths
1028+
*/
1029+
export function get_y(vector : Vector3) : number {
1030+
checkVector3Parameter(vector);
1031+
return vector.y;
1032+
}
1033+
1034+
/**
1035+
* Get the Z component of a 3D vector
1036+
* @param vector The 3D vector
1037+
*
1038+
* @return The Z component of the given vector
1039+
*
1040+
* @category Maths
1041+
*/
1042+
export function get_z(vector : Vector3) : number {
1043+
checkVector3Parameter(vector);
1044+
return vector.z;
1045+
}
1046+
1047+
/**
1048+
* Scales a 3D vector with the given factor.
1049+
* @param vector The original vector
1050+
* @param factor The scaling factor.
1051+
* @return The scaled vector
1052+
*
1053+
* @category Maths
1054+
*/
1055+
export function scale_vector(vector : Vector3, factor : number) : Vector3 {
1056+
checkVector3Parameter(vector);
1057+
checkParameterType(factor, 'number');
1058+
return scaleVector(vector, factor);
1059+
}
1060+
1061+
/**
1062+
* Add two 3D vectors together.
1063+
* @param vectorA The first vector
1064+
* @param vectorB The second vector.
1065+
* @return The sum of the two vectors
1066+
*
1067+
* @category Maths
1068+
*/
1069+
export function add_vector(vectorA : Vector3, vectorB : Vector3) : Vector3 {
1070+
checkVector3Parameter(vectorA);
1071+
checkVector3Parameter(vectorB);
1072+
return addVector(vectorA, vectorB);
1073+
}
1074+
1075+
/**
1076+
* Calcuate the dot product of two 3D vectors.
1077+
* @param vectorA The first vector
1078+
* @param vectorB The second vector.
1079+
* @return The dot product
1080+
*
1081+
* @category Maths
1082+
*/
1083+
export function dot(vectorA : Vector3, vectorB : Vector3) : number {
1084+
checkVector3Parameter(vectorA);
1085+
checkVector3Parameter(vectorB);
1086+
return dotProduct(vectorA, vectorB);
1087+
}
1088+
1089+
/**
1090+
* Calcuate the cross product of two 3D vectors.
1091+
* @param vectorA The first vector
1092+
* @param vectorB The second vector.
1093+
* @return The cross product
1094+
*
1095+
* @category Maths
1096+
*/
1097+
export function cross(vectorA : Vector3, vectorB : Vector3) : Vector3 {
1098+
checkVector3Parameter(vectorA);
1099+
checkVector3Parameter(vectorB);
1100+
return crossProduct(vectorA, vectorB);
1101+
}
1102+
1103+
/**
1104+
* Normalize a vector. The returned vector will have the same direction as the original vector but have a magnitude of 1.
1105+
* @param vector The original vector
1106+
* @return The normalized vector. This function will return a zero vector if the original vector is a zero vector.
1107+
*
1108+
* @category Maths
1109+
*/
1110+
export function normalize(vector : Vector3) : Vector3 {
1111+
checkVector3Parameter(vector);
1112+
return normalizeVector(vector);
1113+
}
1114+
1115+
/**
1116+
* Calcuate the magnitude of a vector
1117+
* @param vector The vector
1118+
* @return The magnitude of the vector
1119+
*
1120+
* @category Maths
1121+
*/
1122+
export function magnitude(vector : Vector3) : number {
1123+
checkVector3Parameter(vector);
1124+
return vectorMagnitude(vector);
1125+
}
1126+
1127+
/**
1128+
* Get the zero vector
1129+
* @return The zero vector
1130+
*
1131+
* @category Maths
1132+
*/
1133+
export function zero_vector() : Vector3 {
1134+
return zeroVector();
1135+
}
1136+
1137+
/**
1138+
* Calcuate the distance between two 3D points
1139+
*
1140+
* @param pointA The first point
1141+
* @param pointB The second point
1142+
*
1143+
* @return The value of the distance between the two points
1144+
*
1145+
* @category Maths
1146+
*/
1147+
export function point_distance(pointA : Vector3, pointB : Vector3) : number {
1148+
checkVector3Parameter(pointA);
1149+
checkVector3Parameter(pointB);
1150+
return pointDistance(pointA, pointB);
1151+
}

0 commit comments

Comments
 (0)