You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity迷宫游戏中检测/阻止玩家截图的实现方案(C#)

在Unity中实现迷宫游戏的防截图/截图检测方案

嘿,这个需求太贴合你的场景了——限时30秒展示迷宫,就是要避免玩家靠截图作弊嘛。在Unity里确实有不少可行方案,不过得结合你目标的平台来选,毕竟不同系统的截图机制差异不小,咱们一步步拆解:

一、系统级阻止截图(最直接,分平台实现)

这种方式能让系统自带的截图工具(比如Windows的PrintScreen、iOS的电源+音量键)直接抓不到画面,是最有效的硬限制。

Windows平台

可以调用Windows API的SetWindowDisplayAffinity函数,把Unity游戏窗口标记为“不可捕获”,系统级截图工具就会得到黑屏或者空白画面。

在C#中实现的代码示例:

using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class AntiScreenshotWindows : MonoBehaviour
{
    [DllImport("user32.dll")]
    private static extern bool SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);

    private const uint WDA_MONITOR = 0x00000001;
    private const uint WDA_NONE = 0x00000000;

    void Start()
    {
        // 获取Unity窗口句柄
        IntPtr hwnd = UnityEngine.Windows.Window.GetWindowPtr();
        // 设置窗口不可被捕获
        SetWindowDisplayAffinity(hwnd, WDA_MONITOR);
    }

    void OnDestroy()
    {
        // 退出时恢复正常
        IntPtr hwnd = UnityEngine.Windows.Window.GetWindowPtr();
        SetWindowDisplayAffinity(hwnd, WDA_NONE);
    }
}

macOS平台

macOS可以通过NSWindow的setExcludedFromWindowsSnapshot:方法,让系统快照工具跳过你的游戏窗口。需要通过C#调用Objective-C的API:

using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class AntiScreenshotMac : MonoBehaviour
{
    [DllImport("libobjc.dylib")]
    private static extern IntPtr objc_getClass(string className);

    [DllImport("libobjc.dylib")]
    private static extern IntPtr objc_msgSend(IntPtr receiver, IntPtr selector);

    [DllImport("libobjc.dylib")]
    private static extern IntPtr sel_registerName(string selectorName);

    void Start()
    {
        IntPtr nsWindowClass = objc_getClass("NSWindow");
        IntPtr mainWindowSelector = sel_registerName("mainWindow");
        IntPtr mainWindow = objc_msgSend(nsWindowClass, mainWindowSelector);

        IntPtr excludeSelector = sel_registerName("setExcludedFromWindowsSnapshot:");
        // 传入YES(1)设置排除快照
        objc_msgSend(mainWindow, excludeSelector, new IntPtr(1));
    }

    void OnDestroy()
    {
        IntPtr nsWindowClass = objc_getClass("NSWindow");
        IntPtr mainWindowSelector = sel_registerName("mainWindow");
        IntPtr mainWindow = objc_msgSend(nsWindowClass, mainWindowSelector);

        IntPtr excludeSelector = sel_registerName("setExcludedFromWindowsSnapshot:");
        // 恢复正常
        objc_msgSend(mainWindow, excludeSelector, new IntPtr(0));
    }
}

移动端(iOS/Android)

iOS

iOS系统会在用户截图后发送UIApplicationUserDidTakeScreenshotNotification通知,你可以监听这个通知来触发响应(比如立刻隐藏迷宫、弹出警告)。

Unity中可以通过原生绑定实现:

using UnityEngine;

public class ScreenshotDetectoriOS : MonoBehaviour
{
    #if UNITY_IOS && !UNITY_EDITOR
    [System.Runtime.InteropServices.DllImport("__Internal")]
    private static extern void RegisterScreenshotNotification();

    void Start()
    {
        RegisterScreenshotNotification();
    }

    // 由iOS原生代码调用的回调方法
    public void OnScreenshotTaken()
    {
        Debug.Log("用户截图了!");
        // 这里写你的处理逻辑:比如隐藏迷宫、终止倒计时
        MazeManager.Instance.HideMaze();
    }
    #endif
}

然后需要在iOS导出的Xcode工程中添加对应的Objective-C代码(或者用Unity的PostProcessBuild来自动注入):

#import <UIKit/UIKit.h>

extern "C" void RegisterScreenshotNotification() {
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        UnitySendMessage("ScreenshotDetector", "OnScreenshotTaken", "");
    }];
}

Android

Android 12及以上可以设置FLAG_SECURE窗口标记,直接阻止系统截图和录屏;同时也可以监听截图文件的创建来检测行为。

设置FLAG_SECURE的代码示例:

using UnityEngine;

public class AntiScreenshotAndroid : MonoBehaviour
{
    #if UNITY_ANDROID && !UNITY_EDITOR
    void Start()
    {
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        AndroidJavaObject window = currentActivity.Call<AndroidJavaObject>("getWindow");
        // 设置FLAG_SECURE
        window.Call("addFlags", 0x00002000); // FLAG_SECURE的数值
    }

    void OnDestroy()
    {
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        AndroidJavaObject window = currentActivity.Call<AndroidJavaObject>("getWindow");
        // 移除标记
        window.Call("clearFlags", 0x00002000);
    }
    #endif
}

如果需要检测截图(兼容低版本Android),可以监听媒体库的变化,当有新的截图文件添加时触发处理逻辑,这部分需要写Android原生插件来实现。

二、通用视觉干扰方案(跨平台备选)

如果系统级方案无法覆盖所有场景(比如第三方截图工具),可以在迷宫展示时叠加一层动态干扰元素:

  • 快速闪烁的半透明色块,让截图内容模糊不清
  • 随时间快速移动的水印/遮挡层
  • 迷宫元素快速轻微抖动,截图后无法清晰辨认

这种方法体验上会有一点影响,但胜在跨平台,而且能应对大部分非硬件级的截图工具。

三、注意事项

  • 没有100%完美的防截图方案,比如硬件级截图工具、虚拟机内的截图可能绕过系统限制,所以建议结合阻止+检测两种方式:一旦检测到截图行为,立刻终止迷宫展示并提示玩家。
  • 部分平台的防截图设置可能会影响录屏、投屏等功能,记得在游戏说明里告知玩家。

内容的提问来源于stack exchange,提问作者mesrefoglu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:23:59