{"id":20444944,"url":"https://github.com/snapchat/camera-kit-unity-sample","last_synced_at":"2025-08-15T14:14:13.126Z","repository":{"id":196022953,"uuid":"692140343","full_name":"Snapchat/camera-kit-unity-sample","owner":"Snapchat","description":"Sample app for Camera Kit in Unity","archived":false,"fork":false,"pushed_at":"2025-03-07T01:26:17.000Z","size":89550,"stargazers_count":32,"open_issues_count":3,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-26T18:21:22.059Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Snapchat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2023-09-15T16:43:47.000Z","updated_at":"2025-03-07T01:26:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"5c9d5cd7-7aff-40f6-95da-a808a35661f8","html_url":"https://github.com/Snapchat/camera-kit-unity-sample","commit_stats":null,"previous_names":["snapchat/camera-kit-unity-sample"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snapchat%2Fcamera-kit-unity-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snapchat%2Fcamera-kit-unity-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snapchat%2Fcamera-kit-unity-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Snapchat%2Fcamera-kit-unity-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Snapchat","download_url":"https://codeload.github.com/Snapchat/camera-kit-unity-sample/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248648862,"owners_count":21139371,"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":[],"created_at":"2024-11-15T10:10:15.281Z","updated_at":"2025-04-13T00:23:51.133Z","avatar_url":"https://github.com/Snapchat.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Camera Kit Unity Template\n\n\u003e [!IMPORTANT] \n\u003e This repository contains example projects to help you get started with Camera Kit integrations. The software is provided \"as is\" without any warranties or guarantees, and it is not officially supported for production use.\n\nThis is a template project that allows you to build a Unity application and leverage Snap's Camera Kit technology. It supports both iOS and Android builds.\n\n## Requirements\n- Unity 2022.3.17f1\n- Camera Kit SDK 1.26.1 (compatible with Lens Studio v4.55.1)\n- Android: \n  - Android Studio Flamingo (Min SDK version 22, Target SDK version 33)\n  - Gradle 7.2\n- iOS:\n  - XCode 15\n  - Cocoapods\n\n## Project structure\nThis project makes use of [Unity as a Library](https://github.com/Unity-Technologies/uaal-example) to integrate an Unity project with Camera Kit's native iOS and Android SDKs. The fact that we're using Unity as a Library means that the main build of your app will be performed via native build tools ([XCode](https://developer.apple.com/xcode/) for iOS and [Android Studio](https://developer.android.com/studio) for Android). The Unity IDE will not be responsible for building and deploying your code. It will instead export your project as a library tha  is then referenced by the two native apps. That being said, you won't be required to write any native (Swift/Kotlin) code and can still build and configure your app from inside of Unity.\n\nThe project contains the following folders:\n\n- [ios-app/](ios-app/): iOS wrapper\n- [android-app/](android-app/): Android wrapper\n- [unity/](unity/): Unity Project\n- [lenses/](lenses/): Lenses used in the demo\n\n## How to use this template\n\nThe recommended way to use this template is to start by following the App Setup section below and making sure that you can run demo scene and invoke all 3 lenses. After that, you can create your own scenes and delete the assets for the demo scene, which effectively turns your Unity project into a blank project that is set up to build with Camera Kit.\n\n### Development flow\n\nAfter the initial setup described below, you will develop your game/app in Unity as normal. The only difference is during build time. You will ask Unity to export a project source code and then shift focus to the native IDE (XCode or Android Studio) and build your native app from there.\n\n### Application behavior\n\nThe native apps that wrap your Unity application have the sole purpose of connecting Unity with Camera Kit. Your Unity project is the main application logic and will be invoked as soon as the app starts. From Unity's C# code you can invoke Camera Kit. You are not expected to maintain or write new code in Kotlin/Swift.\n\n## App Setup\n\n### Step 1: Account Setup\n\nFollow the steps on the [Camera Kit Documentation](https://docs.snap.com/snap-kit/camera-kit/guides/quick-start/integrate-sdk/setting-up-accounts) to set up your developer account. You should also upload the sample lenses to your own account via [Lens Studio](https://docs.snap.com/lens-studio/references/guides/publishing/submitting/submitting-your-lens). Before moving on to the steps below you should have access to the [Camera Kit Portal](https://camera-kit.snapchat.com/), from where you'll be able to copy the following information:\n\n- An App ID\n- An API Token\n- A Lens Group ID\n  \n### Step 2: Android Setup\n\n1. **In Unity**:\n   1. Open the Unity Project ([unity/](unity/))\n   2. From the toolbar, open the Menu **Camera Kit** -\u003e **Camera Kit Settings...**\n   3. In the dialog that appears, enter your API Key and App ID and press **Save**\n   4. Go to Build Settings and change the Platform to **Android**\n   5. Still in the Build Settings dialog, check the box **Export Project**\n   6. Go to Player Settings -\u003e Settings for Android -\u003e Other Settings, and make sure these options are set\n      - Minimum API level: 22\n      - Scripting Backend: IL2CPP\n      - API Compatibility Level: .NET Standard 2.1\n      - Target architectures: ARMv7, ARM64 \n   7. Now click **Export** and select as an output folder [unity/exports/unity-android-export](unity/exports/unity-android-export/). **⚠️ Important:** If you select a different folder, you will need to specify its path in the Camera Kit Settings dialog.\n\n2. **In Android Studio**:\n   1. File -\u003e Open Project and select the folder [android-app/](android-app/)\n\n3. **Ready!**\n   \n   Now you're be ready to build your application. You can read here more information on [how to build to a device](https://developer.android.com/studio/run) or emulator from Android Studio.\n\n**Note:** This is a one-time set-up.\n\n### Step 3: iOS Setup\n1. In Unity:\n   1. Open the Unity Project ([unity/](unity/))\n   2. From the toolbar, open the Menu **Camera Kit** -\u003e **Camera Kit Settings...**\n   3. In the dialog that appears, enter your API Key and App ID and press **Save**\n   4. Go to Build Settings and change the Platform to **iOS**\n   5. Click on **Build**  and select as output folder: [exports/unity-ios-export/](exports/unity-ios-export/). **⚠️ Important:** If you select a different folder, you will need to specify its path in the Camera Kit Settings dialog.\n2. Click build. Unity will run some postprocessing scripts to prepare your iOS wrapper application\n3. Open [unity-ios/main.xcworkspace](unity-ios/main.xcworkspace/). Here you'll have 3 projects:\n   - Unity-iPhone: autogenerated code created by your Unity app\n   - Pods: autogenerated code created by Cocoapods\n   - UnityWithCameraKit: wrapper native application. That's your main application now, the one you will be deploying. \n4. In XCode:\n   1. Click on **UnityWithCameraKit** -\u003e Signing and Capabilities, and configure your application's provisioning profile and bundle identifier\n   2. Click on **Pods** -\u003e Signing and Capabilities, select the `SCSDKCameraKitReferenceUI` target and choose your Apple Developer team to sign the build\n   3. Right-click [Unity-iPhone/Libraries/Plugins/iOS/NativeCallProxy.h](unity/exports/unity-ios-export/Libraries/Plugins/iOS/NativeCallProxy.h) select \"Show File Inspector\" and in the the right-side Inspector, Target Membership, where the UnityFramework target is selected, change the visibility from \"Project\" to \"Public\"\n   4. Right-click [Unity-iPhone/Data/](unity/exports/unity-ios-export/Data) folder, select \"Show File Inspector\" and in the right side Inspector, Target Membership, de-select Unity-iPhone and select UnityFramework\n5. **Ready!** Now you're be ready to build your application. Building from XCode should be a familiar step since this is the default workflow for Unity developers. Simply remember that your main project is not Unity-iPhone anymore, it's **`UnityWithCameraKit`** instead.\n\n## Camera Kit Guides and Samples\n\n### 1. Sample: Invoking Camera Kit\n```csharp\n// 1. Configure Camera Kit to Launch with a Single Lens, passing launch data\nvar config = new CameraKitConfiguration() \n{ \n   LensId = \"abcde-12345-edcba-54321\",\n   LensGroupId = \"aabbcc-112233-eeddcc-554433\",\n   //...\n};\n\n\n// 2. Invoke Camera Kit\nCameraKit.InvokeCameraKit(config);\n```\n\n\n### 2. Sample: Getting Capture Result\n```csharp\n// 1. Assign a callback go the Remote API Reponse event\nvoid OnEnable()\n{\n   CameraKitHandler.OnCaptureFinished += OnCameraKitCaptured;\n}\n\n// 3. Handle the callback\nvoid OnCameraKitCaptured(string capturedFileUri)\n{\n   Debug.Log(\"Camera Kit captured. File \" + capturedFileUri);\n}\n\n```\n\n### 3. Guide: Sending data from Lens to Unity\n\nWith the setup above, you're able to invoke a Lens that receives data from your Unity logic. This could be sufficient for use cases like using Lenses for try-on, product display, or shareable moments. But if you want to get data back from your Lens into your C# logic, you'll need to make use of Remote APIs.\n\nNote: Remote APIs have this name because they were originally planned to communicate with remote services via HTTP calls. But on Camera Kit, what the Lens invokes as a Lens API actually triggers native code. So we are leveraging what the Lens understands as a Remote API invocation to trigger local logic in the app, and pass data back to Unity. No server-side logic will be required to callback to your Unity app.\n\n#### 3.1 Remote API Set up\nIn order to get a callback from your app, you'll need to configure a Remote API. You can [read more about Remote APIs here](https://docs.snap.com/camera-kit/guides/tutorials/communicating-between-lenses-and-app)\n1. Open the API Dashboard here: [my-lenses.snapchat.com/apis](https://my-lenses.snapchat.com/apis)\n2. Select Add API, and fill out the information as below:\n   1. Target platforms: `CAMERA_KIT`\n   2. Visibility: `Private`\n   3. Host: `unity`\n   4. Security Scheme: `NONE`\n3. **Add Endpoint** with information as below:\n   1.  Reference ID: `unity_send_data`\n   2.  Path: `sendData`\n   3.  Method: `POST`\n   4. **Add Parameter**, and add a Parameter with information as below:\n      1. Name: `unityData`\n      2. Parameter Location: `HEADER`\n      4. Optional: `YES`\n      5. Constant: `NO`\n4. **Add Endpoint** with information as below:\n   1.  Reference ID: `unity_request_state`\n   2.  Path: `requestState`\n   3.  Method: `GET`\n   4.  (No parameters)\n5. Check the confirmation box and click **Submit API**\n\nFrom this moment on, you have a **Remote API Spec ID** in the portal, which you will need for the steps below.\n\n#### 3.2 Sending Remote API calls from Lens (Javascript)\n\nYou can refer to our documentation portal for information on how to use Remote APIs from your Lens :  [Using API Spec in Lens Studio](https://docs.snap.com/camera-kit/guides/tutorials/communicating-between-lenses-and-app#using-api-spec-in-lens-studio)\n\nYou can also refer to the [Coin Collection Lens Sample](lenses/collect-coins/) included in this repository for a working example on how to properly use this API. The relevant code is in [`CoinCollectionController.js`](lenses/collect-coins/Public/Scripts/CoinCollectionController.js)\n\n```javascript\nfunction sendEventToUnity(eventName, eventValue) {\n    var dataToSend = {\n        \"eventName\" : eventName,\n        \"eventValue\" : eventValue\n    };\n    UnityApi.unity_send_data(JSON.stringify(dataToSend), function(err, r){\n        print(\"Data sent to Unity\");\n        print(\"Error? \" + err);\n        print(\"Result? \" + r);\n    })\n}\n```\n\n#### 3.3 Responding to Remote API calls from Unity (C#)\n\n```csharp\n// 1. Modify this class to reflect your API Response\npublic class SerializedResponseFromLens\n{\n   string eventName;\n   string eventValue;\n   //...\n   // You can change this class to match the format of objects you're sending from javascript.\n}\n\n// 2. Pass your Remote API Spec ID when invoking CameraKit\nvar config = new CameraKitConfiguration() {\n   //...\n   RemoteApiSpecId = \"aabbcc-112233-ccbbaa-332211\";\n   //...\n}\nCameraKitHandler.InvokeCameraKit(config);\n        \n// 3. Assign a callback go the Remote API Reponse event\nvoid OnEnable()\n{\n   CameraKitHandler.OnResponseFromLensEvent += OnCameraKitAPIResponse;\n}\n\n// 4. Handle the callback\nvoid OnCameraKitAPIResponse(SerializedResponseFromLens responseObj)\n{\n   Debug.Log(\"Received event! \" + responseObj.eventName);\n}\n\n```\n\n### 4. Guide: Sending data from Unity to Lens\nSince lenses are not set up to receive a constant stream of data from the enclosing app, we are leveraging scheduled Remote API calls (see above) to ping the Unity application multiple times per second and get an updated state from the Unity logic. The script that does this in Lens Studio is configurable so that you can define how many calls per second you want to fire. You can see the script in action in the lens included with this repository. For that, please look at the `RequestUnityState.js` file. The definition of \"state\" here is always a `Dictionary\u003cstring,string\u003e` that will be converted to a JSON string and parsed by the lens.\n\n#### 4.1 Remote API Set up\n\nDefine a new API endpoint in your Unity API with the following settings:\n   1.  Reference ID: `unityRequestState`\n   2.  Path: `unityRequestState`\n   3.  Method: `GET`\n\n\n#### 4.2 From Lens, ask Unity to send updated data (Javascript)\nSince there is no direct method for a lens to receive pushes from an outside context, the lens needs to poll Unity and wait for its response. The provided [Physics Racing Card Demo Lens](lenses/physics-objects/) shows how to fire a request to Unity and keep that request open until Unity is ready to update the Lens State. There relevant script is [**`RequestUnityState.js`**](lenses/physics-objects/Public/Scripts/RequestUnityState.js)\n\n```javascript\nscript.api.requestUpdatedStateFromUnity = function() \n{   \n    ApiModule.unity_request_state(script.api.handleUnityUpdate)\n}\n\nscript.api.handleUnityUpdate = function(err, response) {\n   if (response) {\n      if (response.isPressingButton == \"true\") {\n            global.behaviorSystem.sendCustomTrigger(\"Unity_ButtonDown\");\n      } \n      else if (response.isPressingButton == \"false\") { \n            global.behaviorSystem.sendCustomTrigger(\"Unity_ButtonUp\");\n      } \n   }\n   \n   // As soon as the response is processed, we immediately poll Unity again, leaving another open request, so Unity can send another update to the lens\n   script.api.requestUpdatedStateFromUnity()\n}\n\n// Leave first request open as soon as the lens starts\nscript.api.requestUpdatedStateFromUnity();\n```\n\n#### 4.2 From Unity, send updated data to Lens (C#)\n\nAfter that, you can subscribe to the event and update the Lens State, like so:\n\n```csharp\n    public void OnControllerButtonPressed() {\n        CameraKitHandler.UpdateLensState(new Dictionary\u003cstring, string\u003e() {\n            {\"isPressingButton\", \"true\"}\n        });\n    }\n\n    public void OnControllerButtonReleased() {\n        CameraKitHandler.UpdateLensState(new Dictionary\u003cstring, string\u003e() {\n            {\"isPressingButton\", \"false\"}\n        });\n    }\n```\n\n### 5. Guide: Passing Launch Parameters\n\n#### 5.1 Reading Launch Parameters from Lens (Javascript)\n\nThe provided [Mask Try-on Demo Lens](lenses/mask-tryon/) shows how to read launch parameters passed by Unity as soon as the lens starts up. There relevant script is [**`ParamsManager.js`**](lenses/mask-tryon/Public/ParamsManager.js)\n\n```javascript\nvar launchParams = global.launchParams;\nvar storageKey = \"selectedMask\"\n\nfunction getData() {\n    if (launchParams) {\n        if (launchParams.has(storageKey) ) {\n            selectedMask = launchParams.getString(storageKey);         \n            return true;\n        }\n    return false;\n    }\n}\n```\n#### 5.2 Passing Launch Parameters from Unity (C#)\n\n```csharp\nprivate void InvokeCameraKitWithLaunchParams()\n    {\n        var config = new CameraKitConfiguration()\n        {\n            LensID = \"abcde-1234-edcba-4321\",\n            LensGroupID = \"aabbc-11223-ccbba-33221\"\n            //...\n            LaunchParameters = new Dictionary\u003cstring, string\u003e() {\n                {\"selectedMask\", \"halloween\"}\n            }\n        };\n        CameraKitHandler.InvokeCameraKit(config);\n    }\n```\n\n## API Reference\n\n### Events\n\n#### ⚡️ `OnResponseFromLensEvent`\n\nFires when the CameraKit Lens invokes the `unitySendData` endpoint of the Remote API. \nThis event will contain a `SerializedResponseFromLens` object with data passed by the lens. You can modify the `SerializedResponseFromLens` class to match the data sent by your lens.\n\n#### ⚡️ `OnCameraDismissed`\n\nFires when CameraKit is dismissed.\n\n#### ⚡️ `OnCaptureFinished`\n\nFires when CameraKit finishes capturing. This event will contain an `string` object that contains a path to the captured file.\n\n#### ⚡️ `OnLensRequestedUpdatedState`\n\nFires when CameraKit is asking for an updated State from Unity. You can set your Lens logic to request this at specific times, or on a schedule (multiple times per second) as in the example provided with this repository. To properly respond to this event, call `CameraKitHandler.UpdateLensState` in the event handler.\n\n### Methods\n\n#### ▶️ `DismissCameraKit()`\n\nStops camera and rendering. Sets unity view background color to black.\n\n#### ▶️ `UpdateLensState(Dictionary\u003cstring,string\u003e state)`\n\nUpdates lens state that will be fetched next time the lens requests it.\n\n#### ▶️ `InvokeCameraKit(CameraKitConfiguration config)`\n\nStarts Camera Kit with the provided configuration\n\n### Classes\n\n#### 📦 `CameraKitHandler` class\n\nMonobehavior responsible for bridging native Camera Kit calls and Unity's managed C# code. All its functionalities are accessed statically. It will add itself to the scene upon invocation, and doesn't need to be manually added to the scene hierarchy.\n\n#### 📦 `CameraKitConfiguration` class\n\nContains the following properties to invoke CameraKit\n\n- `LensID`: The ID of the Lens to be invoked\n- `LensGroupID`: The ID of the group to which the lens belongs in the camera kit portal\n- `RemoteAPISpecId`: The ID of the Remote API as defined in My Lenses portal, in case the lens needs to communicate with Unity (optional)\n- `ShutterButtonMode`: Configures how/whether to display the shutter (capture) button\n- `RenderMode`: Configures how to invoke Camera Kit (whether in Full Screen or Behind Unity's surface, seen \"through\" transparent areas)\n- `StartWithCamera`: Configures which Camera (front, back) should be initialized with the Lens\n- `LaunchParameters`: Configures data to be read by the lens at initialization\n- `UnloadLensAfterDismiss`: Configures whether the Lens should be unloaded from memory to have its state reset after being dismissed\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnapchat%2Fcamera-kit-unity-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnapchat%2Fcamera-kit-unity-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnapchat%2Fcamera-kit-unity-sample/lists"}