Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UdonSharp;
- using UnityEngine;
- using VRC.SDKBase;
- using VRC.Udon;
- using VRC.Udon.Common;
- // attachment does most of the stuff, attachment point just stores attachments and clamps position
- // detach only when moved
- // late joiner sync DONE
- // collision prevention TODO
- public class RAttachment : UdonSharpBehaviour
- {
- // main config
- [Header("Config")]
- [Tooltip("String that will be compared against names of the entered triggers to identify attachment points")]
- public string attachmentPointIndentifierString = "AttachmentPoint";
- public int attachmentCompatibilityLayer = 0;
- public float attachmentOffset = 0f;
- public float interpolationTimeSec = 0.25f;
- [Header("Plugins")]
- public UdonBehaviour[] callbackReceivers = null;
- public bool forwardAttachmentPointToCallbackReceivers = false;
- [Header("Audio")]
- public float soundVolume = 0.2f;
- public AudioClip readyToAttachSound = null;
- public AudioClip attachCancelSound = null;
- public AudioClip attachSound = null;
- public AudioClip detachSound = null;
- // PRIVATE VARIABLES
- private RAttachmentPoint _targetAttachmentPoint = null;
- private Transform _initialParent = null;
- private bool isHeld = false;
- private bool isAttached = false;
- // DEBUG
- public RDebug RDbg = null;
- // SYNCED
- [UdonSynced]
- private Vector3 _positionOffset = Vector3.zero;
- [UdonSynced]
- private string _targetAttachmentPointSyncName;
- [UdonSynced]
- private Vector3 _syncPos;
- [UdonSynced]
- private Quaternion _syncRot;
- // interpolation
- private Vector3 _prevPos;
- private Quaternion _prevRot;
- [UdonSynced]
- private bool _interpolate = false;
- private float _timeSpentInterpolating = 0f;
- private bool _syncIsDirty = false;
- // INITIALIZATION
- void Start()
- {
- _initialParent = transform.parent;
- RDbg = GameObject.Find("Dibugir").GetComponent<RDebug>();
- }
- // IMPLEMENTATION
- private void OnAttachSyncReceived(){ // triggered when others are guaranteed to have_targetAttachmentPoint set;
- Debug.Log($"{gameObject.name} OnAttachSyncReceived: attach to {_targetAttachmentPoint}");
- _attachLocal();
- }
- private void OnDetachSyncReceived(){
- Debug.Log($"{gameObject.name} OnDetachSyncReceived: paren changed to {_targetAttachmentPoint}");
- _detachLocal();
- }
- private void _setLocalTransform(){ // zero local position and rotation
- transform.localRotation = Quaternion.identity;
- transform.localPosition = _positionOffset;
- Debug.Log($"new local localPosition: {_positionOffset}");
- }
- private void _attachLocal(){
- Debug.Log($"{gameObject.name} _attachLocal to {_targetAttachmentPoint.gameObject}");
- transform.parent = _targetAttachmentPoint.attachmentParentContainer;
- if(Networking.LocalPlayer.IsOwner(gameObject)){
- _positionOffset = _targetAttachmentPoint.ClampOffset(transform.localPosition);
- _positionOffset.x+=attachmentOffset;
- _interpolate = false;
- Debug.Log($"_positionOffset is calculated to be {_positionOffset} for localPosition: {transform.localPosition}");
- }
- _setLocalTransform(); // move to the position
- isAttached = true;
- _playAttachAudio();
- _sendCallback("OnRAttachmentAttachLocal");
- }
- private void _detachLocal(){
- //Debug.Log($"{gameObject.name} _detachLocal DETACHED FROM {_targetAttachmentPoint}");
- transform.parent = _initialParent;
- isAttached = false;
- if(_targetAttachmentPoint == null) return;
- _targetAttachmentPoint = null;
- //transform.parent = _initialParent;
- //isAttached = false;
- _playDetachAudio();
- _sendCallback("OnRAttachmentDetachLocal");
- }
- private void _syncToOthers(){
- _targetAttachmentPointSyncName = (_targetAttachmentPoint) ? _targetAttachmentPoint.gameObject.name : null;
- Debug.Log($"{gameObject.name} _syncToOthers sent by {Networking.LocalPlayer.displayName}, sent: {_targetAttachmentPointSyncName}");
- RequestSerialization();
- }
- private void _handleSerialization(){
- if(_targetAttachmentPoint == null && _targetAttachmentPointSyncName != ""){
- _targetAttachmentPoint = GameObject.Find(_targetAttachmentPointSyncName).GetComponent<RAttachmentPoint>();
- OnAttachSyncReceived();
- }else if (_targetAttachmentPoint != null && _targetAttachmentPointSyncName == ""){
- OnDetachSyncReceived();
- }
- if(transform.parent == _initialParent){
- _prevPos = transform.localPosition;
- _prevRot = transform.localRotation;
- if(_prevPos == _syncPos && _prevRot == _syncRot) return;
- if(!_interpolate){
- transform.localPosition = _syncPos;
- transform.localRotation = _syncRot;
- }else{
- _timeSpentInterpolating = 0f;
- }
- }
- }
- // COLLISION DETECTION:
- private void OnTriggerEnter(Collider _collider){
- if(_collider.name.IndexOf(attachmentPointIndentifierString) == -1) return;
- if(!Networking.LocalPlayer.IsOwner(gameObject)) return;
- if(!isAttached) _playReadyToAttachAudio();
- _targetAttachmentPoint = _collider.gameObject.GetComponent<RAttachmentPoint>();
- }
- private void OnTriggerExit(Collider _collider){
- if(_collider.name.IndexOf(attachmentPointIndentifierString) == -1) return;
- if(!Networking.LocalPlayer.IsOwner(gameObject)) return;
- if(!isAttached) _playAttachCancelAudio();
- _targetAttachmentPoint = null;
- }
- // EVENTS OWNER SIDE
- public override void OnPickup() // called only by owner // detach here
- {
- isHeld = true;
- Debug.Log($"{this}: OnPickup {gameObject.name}, _targetAttachmentPoint: {_targetAttachmentPoint}");
- _detachLocal();
- _interpolate = true;
- _syncToOthers();
- }
- public override void OnDrop() // called only by owner
- {
- isHeld = false;
- if(_targetAttachmentPoint==null) {
- SendCustomEventDelayedSeconds("syncPos", 0.2f);
- return;
- }
- if(_targetAttachmentPoint.attachmentCompatibilityLayer != this.attachmentCompatibilityLayer) {
- SendCustomEventDelayedSeconds("syncPos", 0.2f);
- return;
- }
- if(Networking.LocalPlayer.IsOwner(gameObject)) Debug.LogWarning($"ON DROP SENT NOT BY OWNER HOW DID YOU DO THIS");
- // attaching
- // set offset here, calculated only by owner then
- _attachLocal();
- _syncToOthers();
- }
- public override void OnDeserialization(){
- _handleSerialization();
- }
- public override void OnPlayerJoined(VRCPlayerApi player){
- if(Networking.LocalPlayer.IsOwner(gameObject)) syncPos();
- }
- // UPDATE LOOP
- public void syncPos(){ // it can be called only by an owner
- _syncPos = transform.localPosition;
- _syncRot = transform.localRotation;
- RequestSerialization();
- }
- void FixedUpdate(){
- if(isHeld){
- syncPos();
- }
- }
- void Update(){
- _interpolationLoop();
- }
- void _interpolationLoop(){
- if(!_interpolate || _timeSpentInterpolating >= interpolationTimeSec) return;
- // if(_syncIsDirty){
- // _timeSpentInterpolating = 0f;
- // _syncIsDirty = false;
- // }
- float _step = _timeSpentInterpolating/interpolationTimeSec;
- Vector3 _nextPos = Vector3.Lerp(_prevPos, _syncPos, _step);
- Quaternion _nextRot = Quaternion.Lerp(_prevRot, _syncRot, _step);
- transform.localPosition = _nextPos;
- transform.localRotation = _nextRot;
- _timeSpentInterpolating += Time.deltaTime;
- if(_timeSpentInterpolating >= interpolationTimeSec){
- transform.localPosition = _syncPos;
- transform.localRotation = _syncRot;
- //_timeSpentInterpolating = 0f;
- }
- //_timeSpentInterpolating = 0f;
- //transform.localPosition = _syncPos;
- //transform.localRotation = _syncRot;
- }
- // CALLBACK SENDER
- private void _sendCallback(string _callback){
- Debug.Log($"{this}: _sendCallback");
- if(callbackReceivers == null) return;
- foreach(UdonBehaviour _receiver in callbackReceivers){
- Debug.Log($"{this}: Sending {_callback} to {_receiver}");
- if(_receiver!=null) _receiver.SendCustomEvent(_callback);
- }
- }
- // API
- public RAttachmentPoint getAttachmentPoint() => _targetAttachmentPoint;
- // AUDIO
- void _playAttachAudio(){
- if(attachSound == null) return;
- AudioSource.PlayClipAtPoint(attachSound, transform.position, soundVolume);
- }
- void _playDetachAudio(){
- if(detachSound == null) return;
- AudioSource.PlayClipAtPoint(detachSound, transform.position, soundVolume);
- }
- void _playReadyToAttachAudio(){
- if(readyToAttachSound == null) return;
- AudioSource.PlayClipAtPoint(readyToAttachSound, transform.position, soundVolume);
- }
- void _playAttachCancelAudio(){
- if(attachCancelSound == null) return;
- AudioSource.PlayClipAtPoint(attachCancelSound, transform.position, soundVolume);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment