{"id":15139000,"url":"https://github.com/zenithval/oscleash","last_synced_at":"2025-08-04T10:38:32.730Z","repository":{"id":155613710,"uuid":"527635881","full_name":"ZenithVal/OSCLeash","owner":"ZenithVal","description":"VRChat OSC tool to move a player in the direction of a stretched Physbone.","archived":false,"fork":false,"pushed_at":"2024-10-06T22:29:56.000Z","size":7939,"stargazers_count":125,"open_issues_count":3,"forks_count":16,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-05T08:04:02.949Z","etag":null,"topics":["vrchat","vrchat-osc","vrchat-sdk3","vrchat-tool"],"latest_commit_sha":null,"homepage":"https://twitter.com/zenithval","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZenithVal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"zenithval"}},"created_at":"2022-08-22T16:01:48.000Z","updated_at":"2025-04-02T18:26:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"4cee527e-85dd-47ab-a158-f75b9e69c09f","html_url":"https://github.com/ZenithVal/OSCLeash","commit_stats":{"total_commits":168,"total_committers":9,"mean_commits":"18.666666666666668","dds":"0.20238095238095233","last_synced_commit":"0be678a33b43e8fc33dc529265704fcc3e5e0cdd"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZenithVal%2FOSCLeash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZenithVal%2FOSCLeash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZenithVal%2FOSCLeash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZenithVal%2FOSCLeash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZenithVal","download_url":"https://codeload.github.com/ZenithVal/OSCLeash/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247305932,"owners_count":20917208,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["vrchat","vrchat-osc","vrchat-sdk3","vrchat-tool"],"created_at":"2024-09-26T08:00:43.488Z","updated_at":"2025-04-05T08:04:13.386Z","avatar_url":"https://github.com/ZenithVal.png","language":"Python","funding_links":["https://ko-fi.com/zenithval"],"categories":[],"sub_categories":[],"readme":"\n\u003cdiv align=\"Center\"\u003e\n    \u003ch3 align=\"Center\"\u003e\n        \u003c!-- \u003ca\u003e\n          \u003cdiv style=\"float:right\"\u003e\n            \u003cimg src=\"https://raw.githubusercontent.com/ZenithVal/OSCLeash/main/Resources/VRChatOSCLeash.png\" alt=\"Icon\" width=\"50\" \u003e\n          \u003c/div\u003e\n        \u003c/a\u003e --\u003e\n        \u003c!-- Todo: Make better header one day --\u003e\n      A VRChat OSC tool to move a player in the direction of a stretched Physbone. \u003cbr\u003e\n      For leashes, tails, or even hand holding!\n    \u003c/h3\u003e\n    \u003cdiv align=\"Center\"\u003e\n      \u003cp align=\"Center\"\u003e\n        \u003ca\u003e\u003cimg alt=\"Latest Version\" src=\"https://img.shields.io/github/v/tag/ZenithVal/OSCLeash?color=informational\u0026label=Version\u0026sort=semver\"\u003e\u003c/a\u003e\n        \u003ca\u003e\u003cimg alt=\"Downloads\" src=\"https://img.shields.io/github/downloads/ZenithVal/OSCLeash/total.svg?label=Downloads\"\u003e\u003c/a\u003e\n        \u003cbr\u003e\n        \u003ca href=\"https://discord.gg/7VAm3twDyy\"\u003e\u003cimg alt=\"Discord Badge\" src=\"https://img.shields.io/discord/955364088156921867?color=5865f2\u0026label=Discord\u0026logo=discord\u0026logoColor=https%3A%2F%2Fshields.io%2Fcategory%2Fother\"/\u003e\u003c/a\u003e\n        \u003ca href=\"https://github.com/ZenithVal/OSCLeash/blob/main/LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/github/license/ZenithVal/OSCLeash?label=Liscense\"\u003e\u003c/a\u003e\n      \u003c/p\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\n\u003c!-- Why you looking at the raw readme, this is horrid to read. --\u003e\n\n# Download \u0026 Setup\nDownload the latest version of OSCLeash [from releases](https://github.com/ZenithVal/OSCLeash/releases). \u003cbr\u003e\n__This app does not provide a model for a Leash at this time.__ \u003cBr\u003e\n\n\u003cdetails\u003e\u003csummary\u003eSetup Steps (Click the Arrow!)\u003c/summary\u003e\n\n1. Grab the prefab `(OSCLeash.prefab)` [from releases](https://github.com/ZenithVal/OSCLeash/releases) and drop it into your Unity project.\n2. Place the prefab on the root of your model. (**NOT a child of armature**) Don't break prefab!\n3. Select the `Leash Physbone` object and assign the Root Transform of the Physbone to the first bone of your leash.\n4. Select the `Compass` object and assign the source of the `Position constraint` to the **first** bone of your leash.\n5. You can find `Aim Needle` as a child of compass. Assign the source of the `Aim Constraint` to the **last** bone of your leash.\n6. (**Optional**) You can animate the compass object off for remote users using IsLocal. \n7. (**Optional**) Cross Quest/PC support? You'll need to sync the Physbone's network ID. **See FAQ.**\n8. Enable OSC in VRChat settings. (Or reset OSC if you updated an avatar!) ~ [Tutorial](https://raw.githubusercontent.com/ZenithVal/OSCLeash/main/Resources/HowResetOSC.png)\n9. Run the OSCLeash app and get pulled about!\n10. Visit [Config](#config) and fine tune settings for your taste\n\n---\n\u003c/details\u003e\u003cbr\u003e\n\nIf you're having issues, make sure to see the [FAQ](#faq) section. \u003cbr\u003e\nIf all else fails, feel free to reach out in the #OSC-Talkin channel in [my Discord](https://discord.gg/7VAm3twDyy) \n\n\u003cbr\u003e\n\n\n# Config\nAfter running OSCleash at least once, an OSCLeash.json file will be generated. \u003cbr\u003e\nThe default install location of OSCLeash is `%LocalAppData%\\Programs\\OSCLeash` \u003cbr\u003e\nYou can open the json file in your favorite text editor and fine tune your OSCLeash.\n\n\u003cdetails\u003e\u003csummary\u003eTable of Configation settings\u003c/summary\u003e\n\n---\n\n| Value                 | Info                                                           | Default     |\n|:--------------------- | -------------------------------------------------------------- |:-----------:|\n| IP                    | Address to send OSC data to                                    | 127.0.0.1   |\n| ListeningPort         | Port to listen for OSC data on                                 | 9001        |\n| Sending port          | Port to send OSC data to                                       | 9000        |\n| RunDeadzone           | Minimum Stretch % to cause running                             | 0.70        |\n| WalkDeadzone          | Minimum Stretch % to start walking                             | 0.15        |\n| StrengthMultiplier    | Multiplies speed values but they can't go above (1.0)          | 1.2         |\n| UpDownCompensation    | % of compensation to apply for Up/Down angles                  | 1.0         |\n| UpDownDeadzone        | Stops movement if pull angle is above/below this. 1.0 Disables | 0.5         |\n| TurningEnabled        | Enable turning functionality                                   | false       |\n| TurningMultiplier     | Adjust turning speed                                           | 0.80        |\n| TurningDeadzone       | Minimum Stretch % to start turning                             | 0.15        |\n| TurningGoal           | Goal degree range for turning. (degrees, 0-144) (0° to 144°)   | 90          |\n| ActiveDelay           | Delay in seconds between OSC messages while active             | 0.02        |\n| InactiveDelay         | Delay in seconds for OSCLeash while not in use                 | 0.5         |\n| Logging               | Logging for Directional compass inputs                         | false       |\n| XboxJoystickMovement  | Alt movement method for an old bug. Removing eventually        | false       |\n| UseOSCQuery           | Enables [OSCQuery](https://docs.vrchat.com/docs/oscquery)      | false       |\n| PhysboneParameters    | A list of Physbones that are leashes                           | see below   |\n| DirectionalParameters | A list of contacts to use for direction calculation            | see below   |\n---\n\u003c/details\u003e\u003cbr\u003e\n\n\u003cdetails\u003e\u003csummary\u003eDefault Config.json\u003c/summary\u003e\n\n---\n```json\n{\n        \"IP\": \"127.0.0.1\",\n        \"ListeningPort\": 9001,\n        \"SendingPort\": 9000,\n        \"RunDeadzone\": 0.70,\n        \"WalkDeadzone\": 0.15,\n        \"StrengthMultiplier\": 1.2,\n        \"UpDownCompensation\": 1.0,\n        \"UpDownDeadzone\": 0.5,\n        \"TurningEnabled\": false,\n        \"TurningMultiplier\": 0.80,\n        \"TurningDeadzone\": 0.15,\n        \"TurningGoal\": 90,\n        \"ActiveDelay\": 0.02,\n        \"InactiveDelay\": 0.5,\n        \"Logging\": false,\n        \"XboxJoystickMovement\": false,\n        \"UseOSCQuery\": false,\n        \n        \"PhysboneParameters\":\n        [\n                \"Leash\"\n        ],\n        \"DirectionalParameters\":\n        {\n                \"Z_Positive_Param\": \"Leash_Z+\",\n                \"Z_Negative_Param\": \"Leash_Z-\",\n                \"X_Positive_Param\": \"Leash_X+\",\n                \"X_Negative_Param\": \"Leash_X-\",\n                \"Y_Positive_Param\": \"Leash_Y+\",\n                \"Y_Negative_Param\": \"Leash_Y-\"\n        }\n}\n```\n---\n\u003c/details\u003e\u003cbr\u003e\n\n\u003cdetails\u003e\u003csummary\u003ePhysbone Parameters\u003c/summary\u003e\n\n---\nThis is a list of all the Physbones you're using with OSCLeash. \u003cbr\u003e \n\n```json\n        \"PhysboneParameters\":\n        [\n            \"Leash\",\n            \"Leash2\",\n            \"Leash3\"\n        ],\n```\n\nOSCLeash listens for the _IsGrabbed and _Stretch parameters for every listed leash.\n\n---\n\u003c/details\u003e\u003cbr\u003e\n\n\u003cdetails\u003e\u003csummary\u003eMultiple Leashes\u003c/summary\u003e\n\n---\nThis requires an understanding of Physbones Parameters, Animations, and Constraints. \u003cbr/\u003e\n - Add a new source to `Compass` and `Aim Needle` for each extra leash. 0 Weight by default\n - Depending on which leash `_IsGrabbed`, animate the weights to match the Grabbed leash.\n\n ---\n\u003c/details\u003e\u003cbr\u003e\n\n\u003cdetails\u003e\u003csummary\u003eTurning Functionality\u003c/summary\u003e\n\n---\n**⚠️ Motion sickness warning ⚠️** \n\nIf you want to enable this feature, set `TurningEnabled` to **True**.\u003cbr/\u003e\n`Currently Supports North, East, South, \u0026 West`\u003cbr/\u003e\n\nIf you had a leash up front and you want to turn to match the direction it's pulled from (EG: a Collar with the leash on the front) Set set the parameter on your Leash Physbone and config to `Leash_North`.\n\n\u003cdetails\u003e\u003csummary\u003eConfig File\u003c/summary\u003e\n\n```json\n        \"PhysboneParameters\":\n        [\n            \"Leash_North\"\n        ],\n```\n\u003c/details\u003e\u003cbr\u003e\n\nWe parse the direction to control turning so `\"Tail_South\"` would work. \u003cbr\u003e\nWhenever this leash is grabbed and pulled past the deadzone it will begin to turn. \u003cbr/\u003eIt will continue to turn until it is greater than the TurningDeadzone value. \u003cbr/\u003e\n\n---\n\n\u003cdetails\u003e\u003csummary\u003eNerd Stuff\u003c/summary\u003e\n\nHere's the simplified logic of the system.\n\n```python\nif LeashDirection == \"North\" and Z_Positive \u003c TurningGoal:\n    TurningSpeed = ((X_Negative - X_Positive) * LeashStretch * TurningMultiplier)\n```\n\u003c/details\u003e\u003cbr\u003e\n\n\u003c/details\u003e\u003cbr\u003e\n\n\u003cdetails\u003e\u003csummary\u003eExtra stuff for nerds!\u003c/summary\u003e\n\n# How OSCLeash works\n\n## Step 1: Get Leash Physbone parameters\n\nWe receive the Leash_Stretch and Leash_Grabbed parameters.  \nIf Leash_Grabbed becomes true, we begin reading Leash_Stretch \n\nWe'll use these values in this example:  \n\n\u003e Leash_IsGrabbed = True\u003cbr/\u003eLeash_Stretch = $0.95$\n\n\n## Step 2: Gather Directional Contact values\n\n\u003cimg src=\"https://cdn.discordapp.com/attachments/606734710328000532/1011420984303165500/Example_Gif.gif\" title=\"\" alt=\"Function Example\" width=\"502\"\u003e \u003cbr\u003e\n4 Contacts (Blue) surround a object with an aim constraint and a contact at the tip. (Yellow) \u003cbr/\u003e\n\nBased on where the constraint is aimed, it will give us 4 values. \u003cbr/\u003e\n\nIf it was pointing South-South-West, we would get:\n\n\u003e Leash_Z+ = $0.0$\u003cbr/\u003eLeash_Z- = $0.75$\u003cbr/\u003eLeash_X+ = $0.0$\u003cbr/\u003eLeash_X- = $0.25$ \n\n\n## Step 3: Math\n\nMath is fun. Add the negative and positive contacts \u0026 multiply by the stretch value.\n\n\u003e (Z_Positive - Z_Negative) * Leash_Stretch = Vertical\u003cbr/\u003e(X_Positive - X_Negative) * Leash_Stretch = Horizontal \n\nSo our calculation for speed output would look like:\n\n\u003e $(0.0 - 0.75) * 0.95 = -0.7125$ = Veritcal\u003cbr/\u003e$(0.0 - 0.25) * 0.95 = -0.2375$ = Horizontal\n\n\n## Step 4: Outputs\n\nIf either value is above the walking deadzone (default 0.15) we start outputting them instead of 0. \u003cbr/\u003eIf either value is above the running deadzone (0.7) we tell the player to run (x2 speed)\n\nAll movement values are relative to the VRC world's movement speed limits. \u003cbr/\u003eSo we'd be moving at $142.5$% speed south and $47.5$% speed to the West. \n\nIf the values are below the deadzones or _IsGrabbed is false, send 0s for the OSC values once to stop movement. \n\n\u003c/details\u003e\n\n\u003cbr\u003e\n\n\n# FAQ\n\n\u003cdetails\u003e\u003csummary\u003eClick to Expand\u003c/summary\u003e\n\u003cbr\u003e\n\u003c!--\n**Q:** \u003cbr\u003e\n**A:** \n--\u003e\n    \n**Q:** OSCLeash.exe is removed by my antivirus. \u003cbr\u003e\n**A1:** This is a false positive I can't really fix. You'll need to add an exclusion. \u003cbr\u003e\n**A2:** Try out the MSI version if you're having trouble with the EXE or build it yourself. \u003cbr\u003e\n\n\n---\n\n**Q:** OSCLeash always says `Started, awaiting input` \u003cbr\u003e\n**A1:** Manually Reset OSC by deleting the OSC and OSC.bak folders at `C:\\Users\\(Your username)\\AppData\\LocalLow\\VRChat\\VRChat` \u003cbr\u003e\n**A2:** Did you do avatar setup correctly? Make sure your leash physbone matches your config. \u003cbr\u003e\n**A3:** This could potentially be a firewall issue, but before that, double check your avatar, please. \u003cbr\u003e\n\n---\n\n**Q:** Missing scripts on prefab \u003cbr\u003e\n**[A1:](https://github.com/ZenithVal/OSCLeash/issues/32)** Your VRC SDK is likely out of date or your project has errors. Please update or fix. \u003cbr\u003e\n**A2:** If using the [Modular Avatar](https://modular-avatar.nadena.dev/) prefab, you'll need to have that installed too.\n\n\n---\n\n**Q:** OSCLeash says grabbed but I don't get moved \u003cbr\u003e\n**A1:** This can happen if your leash physbone does not have any stretch. \u003cbr\u003e\n**A2:** Make sure self interaction is `enabled`, it's needed for the direction calculation.\n\n---\n\n\n**Q:** The direction OSCLeash pulls is not accurate \u003cbr\u003e\n**A1:** Is your physbone too angle limited or short? If it can't move it can't get an accurate location. \u003cbr\u003e\n**A2:** If your scaling up very large, scale down the `Compass` object ~ contacts have a max size. \u003cbr\u003e\n\n---\n\n**Q:** Quest Support \u003cbr\u003e\n**A1:** You'll need to sync the network IDs of your Leash physbone between Quest \u0026 PC. \u003cbr\u003e\nYou can use [VRC's Network ID Utility](https://creators.vrchat.com/worlds/udon/networking/network-id-utility/#:~:text=Network%20IDs%20are%20the%20link,number%20assigned%20to%20a%20GameObject) or the [ID Assigner tool](https://kurotu.github.io/VRCQuestTools/docs/references/components/network-id-assigner/) made by the community. \u003cbr\u003e\n**A2:** The OSCLeash app needs to be run on a PC. *(OSC is over the network though)*\n\n---\n\n**Q:** How can I run OSCLeash with my other OSC apps \u003cbr\u003e\n**A1:** Enable OSCQuery by setting useOSCQuery to `true` in the config.\u003cbr\u003e\n**A2:** Try out a OSC Router, like [OSC Switch](https://github.com/KaleidonKep99/OpenSoundControlSwitch).\u003cbr\u003e \n\n---\n\n**Q:** My Question/Issue isn't answered above \u003cbr\u003e\n**A:** [Discord](https://discord.gg/7VAm3twDyy) or [Git Issue](https://github.com/ZenithVal/OSCLeash/issues)\n\n\n\u003c/details\u003e\u003cbr\u003e\n\n# Future Plans/Goals\n\n- Simple [dOSC](https://github.com/Duinrahaic/dOSC) app version \n- Performant C# Rewrite\n  - Turns out python isn't great for really fast stuff?\n  - Maybe even C++ if masochistic enough.\n- ~~OSCQuery Support (When whitelisting is fixed)~~ \n  - *Whilelisting still isn't fixed but meh*\n- Anchoring leash to a point in world space when posed.\n- Using a player [Contact Tracker](https://github.com/hfcRed/Player-Tracker/tree/main) to follow automatically.\n- Y axis movement via an OVRAS API\n\n# Running from Source\n\nFor those that want to, you can run OSCLeash without an installer or exe.\n- Clone the repo\n- `CD` into the directory\n- Run `pip install -r requirements.txt` \n- Run `OSCLeash.py`\n\n# Credits \u0026 Liscenses\n\n- App Rope Icon | [Game-icons.net](https://game-icons.net/1x1/delapouite/locked-heart.html) under [CC by 3.0](https://creativecommons.org/licenses/by/3.0/)\n- @ALeonic is responsible for a majority of v2 (Threading is scary!)\n- @FrostbyteVR walked me through the proccess of making v1\n- Someone else did this but it was a closed source executable\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenithval%2Foscleash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzenithval%2Foscleash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenithval%2Foscleash/lists"}