private void OnOwnerJoined(SessionId userId) { AgentPrivate agent = ScenePrivate.FindAgent(userId); // Lookup the scene object for this agent ObjectPrivate agentObejct = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (agentObejct == null) { Log.Write($"Unable to find a ObjectPrivate component for user {userId}"); return; } // Lookup the animation component. There should be just one, so grab the first AnimationComponent animationComponent = null; if (!agentObejct.TryGetFirstComponent(out animationComponent)) { Log.Write($"Unable to find an animation component on user {userId}"); return; } animationComponent.Subscribe(StartKey, StartSound); animationComponent.Subscribe(StopKey, StopSound); }
private void UpdateRightPosition() { //Log.Write("In UpdatePosition UserIn is: " + UserIn); //Log.Write("Right: " + agent.GetControlPointPosition(ControlPointType.RightTool)); ObjectPrivate AgentObject = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (MultiClick) { do { Vector AgentPosition = AgentObject.Position; Quaternion AgentRotation = AgentObject.Rotation; Vector RightPosition = agent.GetControlPointPosition(ControlPointType.RightTool); Vector WorldRightPosition = LocalToWorld(AgentPosition, AgentRotation, RightPosition); RightActionToPerform(RightPosition, WorldRightPosition, AgentPosition, AgentRotation); Wait(TimeSpan.FromMilliseconds(timeDelay)); }while (UserIn && RightTriggerPressed); } else { //do once Vector AgentPosition = AgentObject.Position; Quaternion AgentRotation = AgentObject.Rotation; Vector RightPosition = agent.GetControlPointPosition(ControlPointType.RightTool); Vector WorldRightPosition = LocalToWorld(AgentPosition, AgentRotation, RightPosition); RightActionToPerform(RightPosition, WorldRightPosition, AgentPosition, AgentRotation); } //Log.Write("Out of Loop"); }
private void newUser(UserData data) { AgentPrivate agentPrivate = ScenePrivate.FindAgent(data.User); ObjectPrivate objectPrivate = ScenePrivate.FindObject(agentPrivate.AgentInfo.ObjectId); reset(agentPrivate, objectPrivate); }
// Logic! public override void Init() { // Subscribe to the interaction, meaning this next block of code will be executed when the object is clicked on MyInteraction.Subscribe((InteractionData data) => { // Get the agent that clicked on this object var agent = ScenePrivate.FindAgent(data.AgentId); if (agent != null) { if (ObjectPrivate.IsMovable) { // Calculate the XY difference from the agent to the object Vector toObject = ObjectPrivate.Position - ScenePrivate.FindObject(agent.AgentInfo.ObjectId).Position; toObject.Z = 0.0f; // If there is an XY difference in position if (toObject.LengthSquared() > 0.0f) { // Normalize the direction vector toObject = toObject.Normalized(); // Smoothly move the object away from the agent by the specified distance ObjectPrivate.Mover.AddTranslate(ObjectPrivate.Position + toObject * Distance, Seconds, MoveMode.Smoothstep); } } else { ShowNotMovableReason(agent); } } }); }
private void SubscribeToHotkey(SessionId userId) { AgentPrivate agent = ScenePrivate.FindAgent(userId); // Lookup the scene object for this agent ObjectPrivate agentObejct = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (agentObejct == null) { Log.Write($"Unable to find a ObjectPrivate component for user {userId}"); return; } // Lookup the animation component. There should be just one, so grab the first AnimationComponent animationComponent = null; if (!agentObejct.TryGetFirstComponent(out animationComponent)) { Log.Write($"Unable to find an animation component on user {userId}"); return; } // Listen for a key press. Since the agent will be teleporting away, do no request a persistent subscription animationComponent.Subscribe(TeleportHotkey, TeleportToNext, false); }
private void LocalTeleport(ScriptEventData data) { Log.Write("A"); foreach (AgentPrivate agent in ScenePrivate.GetAgents()) { Log.Write(agent.AgentInfo.Name); if (agent.AgentInfo.Name == "GranddadGotMojo") { Log.Write("Camaeraman found"); ObjectPrivate objectPrivate = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (objectPrivate != null) { AnimationComponent anim = null; if (objectPrivate.TryGetFirstComponent(out anim)) { if (RelativeDestination) { anim.SetPosition(Destination + ObjectPrivate.Position); } else { anim.SetPosition(Destination); } } } } } }
public void Check() { List <ObjectId> keys = new List <ObjectId>(AllObjects.Keys); foreach (var opId in keys) { ObjectPrivate op = ScenePrivate.FindObject(opId); if (op == null || !op.IsValid) { Error(op.Name); AllObjects.Remove(opId); continue; } int oldScriptCount = AllObjects[opId]; int newScriptCount = op.LookupScripts().Length; if (oldScriptCount > newScriptCount) { Error(op.Name); } // Either still initializing and adding scripts or only logging. AllObjects[opId] = newScriptCount; } }
private void findColliders(List <RigidBodyComponent> colliders, ObjectId id) { if (!ToggleCollisions) { return; } ObjectPrivate op = ScenePrivate.FindObject(id); if (op != null) { for (uint rbi = 0; rbi < op.GetComponentCount(ComponentType.RigidBodyComponent); ++rbi) { if (op.TryGetComponent(rbi, out RigidBodyComponent rb)) { if (rb != null) { if (colliders.Contains(rb)) { return; } colliders.Add(rb); } } } } }
bool ResetToInitialPosition(RigidBodyComponent rigidBody) { ObjectPrivate objectPrivate = ScenePrivate.FindObject(rigidBody.ComponentId.ObjectId); if (objectPrivate != null && objectPrivate.IsValid) { try { var motionType = rigidBody.GetMotionType(); WaitFor(rigidBody.SetMotionType, RigidBodyMotionType.MotionTypeKeyframed); rigidBody.SetAngularVelocity(Vector.Zero); rigidBody.SetLinearVelocity(Vector.Zero); rigidBody.SetOrientation(objectPrivate.InitialRotation); rigidBody.SetPosition(objectPrivate.InitialPosition); rigidBody.SetMotionType(motionType); return(true); } catch { Log.Write(LogLevel.Error, __SimpleTag, "Position Reset: error resetting object position."); } } return(false); }
bool Reset(RigidBodyComponent rigidBody) { if (!rigidBody.IsValid) { Log.Write(LogLevel.Warning, __SimpleTag, "Position Reset: object is no longer in the scene, removing from reset script."); return(false); } if (rigidBody.GetHeldObjectInfo().IsHeld) { // Check now that the object is still in the scene. if (null == ScenePrivate.FindObject(rigidBody.ComponentId.ObjectId)) { return(false); } if (ForceDrop) { rigidBody.ReleaseHeldObject((d) => { ResetToInitialPosition(rigidBody); }); } else { rigidBody.SubscribeToHeldObject(HeldObjectEventType.Release, (d) => { ResetToInitialPosition(rigidBody); }, false); } return(true); } else { return(ResetToInitialPosition(rigidBody)); } }
private void PressedSpecial(AnimationData data, string key) { AgentPrivate agent = ScenePrivate.FindAgent(data.ComponentId.ObjectId); string res = ""; if (agent == null) { Log.Write(LogLevel.Warning, GetType().Name, $"no agent"); return; } string name = agent.AgentInfo.Name; //Log.Write(LogLevel.Warning, GetType().Name, $"{name} Pressed {key}"); addKeys(name, key); if (isSecret(name)) { players[name] = ""; res = do_dialog(agent, "You found the secret key combination!\nWould you like to teleport to the secret spot?"); if (res == "Yes") { AnimationComponent comp; if (ScenePrivate.FindObject(data.ComponentId.ObjectId).TryGetFirstComponent <AnimationComponent>(out comp)) { comp.SetPosition(secretloc); } } } }
private void LocalTeleport(int MoveNumber, ScriptEventData data) { Log.Write("MoveNumber: " + MoveNumber); LastCameraMan = CameraMan; foreach (AgentPrivate agent in ScenePrivate.GetAgents()) { Log.Write(agent.AgentInfo.Name); if (agent.AgentInfo.Name == CameraMan) { Log.Write("Camaeraman found"); ObjectPrivate objectPrivate = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (objectPrivate != null) { AnimationComponent anim = null; if (objectPrivate.TryGetFirstComponent(out anim)) { RigidBody.SetPosition(MoveVector[MoveNumber]); Wait(TimeSpan.FromSeconds(0.05)); anim.SetPosition(MoveVector[MoveNumber]); Wait(TimeSpan.FromSeconds(0.05)); Quaternion rotation = Quaternion.FromEulerAngles(Mathf.RadiansPerDegree * RotateVector[MoveNumber]); RigidBody.SetOrientation(rotation); //PlayMovement(MoveNumber, data); } } } } }
private void Start(ScriptEventData sed) { ISimpleData idata = sed.Data.AsInterface <ISimpleData>(); if (idata != null && idata.AgentInfo != null) { AgentPrivate agent = ScenePrivate.FindAgent(idata.AgentInfo.SessionId); ObjectPrivate agentObject = ScenePrivate.FindObject(idata.AgentInfo.ObjectId); if (agent == null || agentObject == null || !agent.IsValid) { return; } try { Guid agentId = agent.AgentInfo.AvatarUuid; UIProgressBar thisBar; if (_agentProgressBars.TryGetValue(agentId, out thisBar) && thisBar != null && thisBar.IsValid) { // if this script is already showing the progress bar to this agent, ignore the start event. return; } // cancel any progress bar that has been started by another script foreach (UIProgressBar otherBar in agent.Client.UI.GetProgressBars()) { if (otherBar.IsValid) { otherBar.Cancel(); } } UIProgressBar bar = agent.Client.UI.AddProgressBar(); bar.Start(LabelString, Duration, Color, (OperationCompleteEvent completeEvent) => { OnBarComplete(agent.AgentInfo, completeEvent); }); _agentProgressBars[agentId] = bar; if (CancelOnMove) { CancelOnMoveCoroutine(agentId, agentObject, bar); } else { RemoveFromDictionaryCoroutine(agentId, bar); } } catch { } } else { Log.Write(LogLevel.Error, "Could not obtain agent data from progress bar start event."); } }
public void Detect(ScriptEventData data) { try { PeopleInRange = 0; AgentInDetectionRange = false; foreach (AgentPrivate agent in ScenePrivate.GetAgents()) { float agentDist = (ScenePrivate.FindObject(agent.AgentInfo.ObjectId).Position - ObjectPrivate.Position).Length(); Log.Write("Agent: " + agent.AgentInfo.Name); Log.Write("agentDist: " + agentDist); Log.Write("DetectionRange: " + DetectionRange); if (agentDist <= DetectionRange) { SimpleData sd = new SimpleData(this); Log.Write("A"); sd.AgentInfo = agent.AgentInfo; Log.Write("B"); sd.ObjectId = agent.AgentInfo.ObjectId; Log.Write("C"); sd.SourceObjectId = ObjectPrivate.ObjectId; Log.Write("D"); AgentInDetectionRange = true; Log.Write("E"); SendToAll(OnDetection, sd); Log.Write("In Range"); PeopleInRange++; ObjectPrivate objectPrivate = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (objectPrivate != null) { AnimationComponent anim = null; if (objectPrivate.TryGetFirstComponent(out anim)) { anim.SetPosition(Destination); } } } } if (PeopleInRange == 0) { } } catch (Exception ex) { if (__SimpleDebugging) { Log.Write(LogLevel.Error, __SimpleTag, "Proximity Detection Failed: " + ex.Message); } } }
private string GenerateHintText(string hint, AgentInfo info, ISimpleData data) { if (hint.Contains("{")) { hint = hint.Replace("{Player.Name}", info.Name).Replace("{Object.Name}", ObjectPrivate.Name); ObjectPrivate source = ScenePrivate.FindObject(data.SourceObjectId); if (source != null) { hint = hint.Replace("{Data.Source}", source.Name); } } return(hint); }
private void LocalTeleport(SessionId sessionId) { try { Vector teleportPosition = Destination; Vector teleportForward = NormalizedForward; AgentPrivate agent = ScenePrivate.FindAgent(sessionId); if (UseAvatarRotation) { if (agent != null && agent.IsValid) { ObjectPrivate agentObject = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (agentObject != null) { teleportForward = agentObject.ForwardVector; } } } else { if (RelativePosition) { if (RelativeRotation) { teleportPosition = ObjectPrivate.Position + Destination.Rotate(ObjectPrivate.Rotation); } else { teleportPosition = ObjectPrivate.Position + Destination; } } if (RelativeRotation) { teleportForward = NormalizedForward.Rotate(ObjectPrivate.Rotation); } } if (agent != null) { agent.Client.TeleportTo(teleportPosition, teleportForward); } } catch (NullReferenceException nre) { SimpleLog(LogLevel.Info, "NullReferenceException local teleporting user (maybe they just left): " + nre.Message); } catch (Exception e) { SimpleLog(LogLevel.Error, "Exception local teleporting user: " + e.Message); } }
public override void Init() { // Write an error to the debug console if the object is not movable // (The debug console is visible to the creator with the Ctrl+D keyboard shortcut) if (!ObjectPrivate.IsMovable) { Log.Write($"MoverExample3 script can't move {ObjectPrivate.Name} because either the 'Movable from Script' flag was not set or the object does not have 'Keyframed' physics!"); return; } MyInteraction.Subscribe((InteractionData data) => { // Find the agent that initiated the interaction var agent = ScenePrivate.FindAgent(data.AgentId); if (agent != null) { Vector fromAgentToObject = ObjectPrivate.Position - ScenePrivate.FindObject(agent.AgentInfo.ObjectId).Position; Log.Write("Object position minus agent position Vector " + fromAgentToObject); // Remove any vertical difference fromAgentToObject.Z = 0.0f; //Log.Write("magnitude of the vector, length squared " + fromAgentToObject.LengthSquared()); if (fromAgentToObject.LengthSquared() > 0.0f) { fromAgentToObject = fromAgentToObject.Normalized(); Log.Write("fromAgentToObject.Normalized() " + fromAgentToObject); // Disable interaction MyInteraction.SetEnabled(false); // Clear any other queued movement ObjectPrivate.Mover.StopAndClear(); // rotation and translation Quaternion rot = ObjectPrivate.Rotation; Quaternion stepRot = Quaternion.FromEulerAngles(new Vector(0, 0, (float)Math.PI / 2f)); rot *= stepRot; ObjectPrivate.Mover.AddRotate(rot); ObjectPrivate.Mover.AddTranslate(ObjectPrivate.Position + Vector.ObjectLeft.Rotate(rot), 2.0, MoveMode.Linear); // Enable interaction MyInteraction.SetEnabled(true); } } }); }
// Logic! public override void Init() { // Write an error to the debug console if the object is not movable // (The debug console is visible to the creator with the Ctrl+D keyboard shortcut) if (!ObjectPrivate.IsMovable) { Log.Write($"MoverExample3 script can't move {ObjectPrivate.Name} because either the 'Movable from Script' flag was not set or the object does not have 'Keyframed' physics!"); return; } MyInteraction.Subscribe((InteractionData data) => { // Find the agent that initiated the interaction var agent = ScenePrivate.FindAgent(data.AgentId); if (agent != null) { Vector fromAgentToObject = ObjectPrivate.Position - ScenePrivate.FindObject(agent.AgentInfo.ObjectId).Position; // Remove any vertical difference fromAgentToObject.Z = 0.0f; if (fromAgentToObject.LengthSquared() > 0.0f) { fromAgentToObject = fromAgentToObject.Normalized(); // Disable interaction MyInteraction.SetEnabled(false); // Clear any other queued movement ObjectPrivate.Mover.StopAndClear(); // Flee away from the agent WaitFor(ObjectPrivate.Mover.AddTranslate, ObjectPrivate.Position + fromAgentToObject * FleeDistance, FleeSeconds, MoveMode.EaseOut); // Enable interaction MyInteraction.SetEnabled(true); } } }); // Start spinning if (SpinSpeed > 0.0f) { StartCoroutine(Spin); } }
public override void Init() { // Listen for the 'on' message SubscribeToScriptEvent("on", (ScriptEventData data) => { ISimpleData idata = data.Data.AsInterface <ISimpleData>(); if (idata == null) { ScenePrivate.Chat.MessageAllUsers("The 'on' message does not have a simple script payload!"); } else { ObjectPrivate obj = ScenePrivate.FindObject(idata.ObjectId); ScenePrivate.Chat.MessageAllUsers("The 'on' message simple script payload came from " + obj.Name); } }); }
private void Show(ScriptEventData sed) { ISimpleData idata = sed.Data.AsInterface <ISimpleData>(); if (idata != null && idata.AgentInfo != null) { AgentPrivate agent = ScenePrivate.FindAgent(idata.AgentInfo.SessionId); ObjectPrivate agentObject = ScenePrivate.FindObject(idata.AgentInfo.ObjectId); if (agent == null || agentObject == null || !agent.IsValid) { return; } try { SessionId sessionId = agent.AgentInfo.SessionId; CancelHideTimer(sessionId); agent.Client.UI.HintText = m_textString; if (ShowDuration > 0.01f) { agentTimers.Add(sessionId, Timer.Create(ShowDuration, () => { HideForSessionId(sessionId); })); } if (CancelOnMove) { StartCoroutine(() => CancelOnMoveCoroutine(agentObject, agent, sessionId)); } } catch (ArgumentException) { Log.Write(LogLevel.Error, "Error setting text, bad string?"); } catch { Log.Write(LogLevel.Warning, "Error setting text, agent might have left"); } } else { Log.Write(LogLevel.Error, "Could not obtain agent data from text box show event."); } }
private void SubscribeToHotkey(SessionId userId) { AgentPrivate agent = ScenePrivate.FindAgent(userId); // Lookup the scene object for this agent ObjectPrivate agentObject = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (agentObject != null) { // Lookup the animation component. There should be just one, so grab the first AnimationComponent animationComponent = null; if (agentObject.TryGetFirstComponent(out animationComponent)) { // Listen for the correct event to fire the projectile. animationComponent.Subscribe(ListenEvent, (data) => { OnFire(animationComponent); }, false); } } }
void CharSound(UserData data, SoundResource snd) { float loud = 0.0f; PlaySettings psonce = PlaySettings.PlayOnce; psonce.Loudness = loud; AgentPrivate agent = ScenePrivate.FindAgent(data.User); ObjectPrivate obj = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (snd != null) { agent.PlaySoundAtPosition(snd, obj.Position, psonce); } else { Log.Write(LogLevel.Error, GetType().Name, $"No Sound"); } }
protected void DistanceCheck(AgentPrivate agent, UIProgressBar bar, int index = -1) { ObjectPrivate op; Vector startingPosition; try { op = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (op == null || !op.IsValid) { return; } startingPosition = op.Position; } catch (Exception) { return; } while (true) { try { if (!agent.IsValid || !op.IsValid || !bar.IsValid) { return; } if ((op.Position - startingPosition).LengthSquared() > CancelDistanceSquared) { bar.Cancel(); } Wait(0.2f); } catch (Exception) { return; } } }
void UserJoin(UserData data) { AgentPrivate agent = ScenePrivate.FindAgent(data.User); ObjectPrivate aobj = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); if (aobj == null) { Log.Write(LogLevel.Error, GetType().Name, $"no obj for user {data.User}"); return; } AnimationComponent anicomp = null; if (!aobj.TryGetFirstComponent(out anicomp)) { Log.Write(LogLevel.Error, GetType().Name, $"no ani comp for user {data.User}"); return; } SubscribeKeys(anicomp); }
private void AddInteraction(RigidBodyComponent volume, string prompt, string events) { if (volume != null && volume.IsValid) { ObjectPrivate op = ScenePrivate.FindObject(volume.ComponentId.ObjectId); if (op != null) { var result = WaitFor(op.AddInteraction, prompt.Replace("\\n", "\n"), StartEnabled) as ObjectPrivate.AddInteractionData; if (result.Success) { SetupInteraction(result.Interaction, events); } else { SimpleLog(LogLevel.Error, "Unable to add Interaction to object " + op.Name + ": " + result.Message); } } } }
// Init() is where the script is setup and is run when the script starts. public override void Init() { foreach (var rb in Objects) { if (rb == null) { continue; } ObjectPrivate op = ScenePrivate.FindObject(rb.ComponentId.ObjectId); if (op != null) { var scripts = op.LookupScripts(); AllObjects.Add(op.ObjectId, scripts == null ? 0 : scripts.Length); } } Timer.Create(60, 60, Check); }
void UpdateFollow() { TimeSpan ts = TimeSpan.FromSeconds(TickTime); while (true) { Wait(ts); if (_followAgent == null) { continue; } Vector agentPos = ScenePrivate.FindObject(_followAgent.AgentInfo.ObjectId).Position + FollowObjectOffset; Vector objectPos = ObjectPrivate.Position; if (FixHeight) { agentPos.Z = objectPos.Z; } Vector toAgent = agentPos - objectPos; Vector toAgentDir = toAgent.Normalized(); // Compute if a movement update would move us closer than the follow distance (or beyond the target) Vector finalPos = objectPos + toAgentDir * MoveSpeed * TickTime; Vector toAgentFromFinalPos = agentPos - finalPos; bool wouldOvershoot = (toAgentFromFinalPos.Dot(toAgentDir) < FollowDistance); Quaternion rotation = Quaternion.ShortestRotation(WorldObjectForward, toAgentDir); // Just rotate to point to the follow target instead of overshooting if (wouldOvershoot) { ObjectPrivate.Mover.AddRotate(rotation, TickTime, MoveMode.Linear); } else { ObjectPrivate.Mover.AddMove(finalPos, rotation, TickTime, MoveMode.Linear); } } }
void AddInteraction(ComponentId componentId, int index) { Interactions.Add(null); ObjectPrivate obj = ScenePrivate.FindObject(componentId.ObjectId); if (obj == null || !obj.IsValid) { return; } obj.AddInteraction(InteractionPrompt, false, (data) => { if (data.Success == true && data.Interaction != null) { Interactions[index] = data.Interaction; data.Interaction.Subscribe((interactData) => OnInteract(interactData, index)); } }); }
private void UpdatePosition() { //Log.Write("In UpdatePosition UserIn is: " + UserIn); //Log.Write("Left: " + agent.GetControlPointPosition(ControlPointType.LeftTool) + " Right: " + agent.GetControlPointPosition(ControlPointType.RightTool)); do { ObjectPrivate AgentObject = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); Vector AgentPosition = AgentObject.Position; Quaternion AgentRotation = AgentObject.Rotation; Vector LeftPosition = agent.GetControlPointPosition(ControlPointType.LeftTool); Vector WorldLeftPosition = LocalToWorld(AgentPosition, AgentRotation, LeftPosition); Vector RightPosition = agent.GetControlPointPosition(ControlPointType.RightTool); Vector WorldRightPosition = LocalToWorld(AgentPosition, AgentRotation, RightPosition); ActionToPerform(LeftPosition, WorldLeftPosition, RightPosition, WorldRightPosition, AgentPosition, AgentRotation); Wait(TimeSpan.FromMilliseconds(timeDelay)); }while (UserIn); //Log.Write("Out of Loop"); }
private void UpdateLoop() { while (true) { //this is only one object, so we have it hard coded in to only follow the first agent., you could split this up later Boolean got1 = false; foreach (AgentPrivate agent in ScenePrivate.GetAgents()) { if (got1 == false) { ObjectPrivate agentObejct = ScenePrivate.FindObject(agent.AgentInfo.ObjectId); AnimationComponent anim; if (agentObejct.TryGetFirstComponent(out anim)) { Sansar.Vector fwd = anim.GetVectorAnimationVariable("LLCameraForward"); //Builds a rotation from the fwd vector Quaternion newRot = Quaternion.FromLook(fwd, Sansar.Vector.Up); //This is a basic check to make sure the camera rotation isnt all 0s if (fwd.LengthSquared() > 0) { try { RigidBody.SetAngularVelocity(Vector.Zero); RigidBody.SetLinearVelocity(Vector.Zero); RigidBody.SetPosition(agentObejct.Position + lightPositionOffset); //Order of multiplication matters here I think, start with the base rotation, //multiply by and base offset rotation for the light, then multiply by the rotation of the fwd //Keep in mind that multiplying quad A by quad b will rotate quad A by quad b RigidBody.SetOrientation(QuaternionToVector(startRot * lightOnObjectDirection * newRot).Normalized()); } catch { } } } got1 = true; } } Wait(TimeSpan.FromSeconds(.05)); } }