Site Search
Homepage of Otaku No Zoku
Complete Archives of Otaku No Zoku
About Otaku No Zoku
Subscribe to Otaku No Zoku
Bookmark Otaku No Zoku

Unity3D Piracy Prevention :

A Unity3D script to prevent your precious web game from being pinched from authorised websites and just hosted somewhere else.

This sort of very simple protection is especially important if you are trying to monetize your web game and do not want it spread around on websites where you don’t see any financial compensation.

If you host on Wooglie.com or Shockwave.com, I highly recommend you at least drop this script in to your project. It’s one more line of defence against random people just swiping your game and hosting it on their own advertising supported website.

How to use: Copy and paste this code in to a new C# script named AntiPiracy.cs and then attach the script to one of your game objects, such as the player, or the main menu. You only need to use it once, and it only needs to execute once.

You specify the list of permitted remote hosts in the Unity3D Inspector. There can be multiple remote hosts, though you should generally create a new build for each website you release your game on as there can only be a single bounce URL. For Wooglie.com your remote hosts would be http://wooglie.com, http://www.wooglie.com and http://contentmirror.wooglie.com. You must put http:// or https:// in front of each of your remote hosts for the script to work. The script is reasonably smart but it cannot work if you give it bad input.

You can change the list of permitted local hosts too, though you shouldn’t need to unless you are doing something unusual. Local hosts are used when you run your game in a web browser from file:// or http://localhost/.

You can specify whether to permit running on local host with a simple check box. This lets you test your game in a web browser by using Build and Run (CTRL+B on Windows) without having to do anything special.

If the piracy test fails, you specify a URL for the web browser to redirect the player to. This can be anything you want, but should probably be the homepage of the game or the correct page for the game on Wooglie.com or Shockwave.com.

You can manually invoke the piracy test by calling the function TestPiracy(). You could test at the beginning of every level if you so desire. Though one test is usually sufficient.

The script runs automatically at start-up. You can disable this behaviour by commenting out the function Start() and then manually invoking the piracy test.

If you want to be really sneaky, you can wait a few levels, or a few minutes before bouncing the player out of the game.

When you create a release build I suggest you disable Permit Local Host in the Inspector unless you want your players to be able to download and play your game from their desktop.

How it works: The script maintains a list of websites that are permitted to host your game. When the script starts up it looks at website it is being hosted on, and if it doesn’t match up with one of the permitted websites you’ve specified, it bounces the player to a webpage that you’ve specified.

Two tests are performed, one with the Unity3D web player, and another in JavaScript. The quick JavaScript test makes sure the Unity3D web player isn’t being spoofed somehow.

Assumptions: This isn’t going to stop anybody really determined. It’s a simple matter for anyone willing to take the time to decompile your entire game and edit the strings containing the list of permitted websites. What it will do is prevent 90% or more of the websites that just harvest random

The License: It’s the GNU Lesser GPL. That means you can take it, modify it, put it in your own game, and so on. You have to leave the copyright notice in place, if you create a modified version and distribute it, you have to supply the source code. You cannot sell the AntiPiracy script, but you can include it in a product that is for sale.

If you represent Wooglie.com, Shockwave.com or any of the other websites out there that host Unity3D games, feel free to link directly to this webpage, and also host the file directly on your own webpage so long as the entire file, including copyright information, remains intact.


/*-----------------------------------------------------------------------------
 * AntiPiracy.cs - Permits the game only to run on allowed hosts
 * Copyright (C) 2010 Justin Lloyd
 * http://www.otakunozoku.com/
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 * 
-----------------------------------------------------------------------------*/

using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Text;


public class AntiPiracy : MonoBehaviour
{
    /// <summary>
    /// Do we permit execution from local host or local file system?
    /// </summary>
    public bool m_permitLocalHost = true;

    /// <summary>
    /// List of permitted remote hosts that host this game.
    /// </summary>
    public string[] m_permittedRemoteHosts;

    /// <summary>
    /// List of permitted localhost URLs
    /// </summary>
    public string[] m_permittedLocalHosts = { "file://", "http://localhost/",
"http://localhost:", "https://localhost/", "https://localhost:" };

    /// <summary>
    /// URL to bounce the player to if they are executing the game from an
unknown URL.
    /// </summary>
    public string m_bounceToURL;

    void Start()
    {
        TestPiracy();
    }

    /// <summary>
    /// Determine if the current host exists in the given list of permitted
hosts.
    /// </summary>
    /// <param name="hosts">An array of hosts permitted to host this game.
</param>
    /// <returns>True if the current host is permitted to host this game.
</returns>
    private bool IsValidHost(string[] hosts)
    {
        // print out list of hosts in debugging build
        if (Debug.isDebugBuild)
        {
            StringBuilder msg = new StringBuilder();
            msg.Append("Checking against list of hosts: ");
            foreach (string url in hosts)
            {
                msg.Append(url);
                msg.Append(",");
            }

            Debug.Log(msg.ToString());
        }

        // check current host against each of the given hosts
        foreach (string host in hosts)
        {
            if (Application.absoluteURL.IndexOf(host) == 0)
            {
                return true;
            }

        }

        return false;
    }

    /// <summary>
    /// Determine if the current host is a valid local host.
    /// </summary>
    /// <returns>True if the game is permitted to execute from local host and
    /// the current host is local host.</returns>
    public bool IsValidLocalHost()
    {
        if (m_permitLocalHost)
        {
            return IsValidHost(m_permittedLocalHosts);
        }

        return false;
    }

    /// <summary>
    /// Determine if the current host is a valid remote host.
    /// </summary>
    /// <returns>True if the game is permitted to execute from the remote host.
</returns>
    public bool IsValidRemoteHost()
    {
        return IsValidHost(m_permittedRemoteHosts);
    }

    /// <summary>
    /// Bounce the player to game's home page
    /// </summary>
    public void Bounce()
    {
        Application.OpenURL(m_bounceToURL);
    }

    /// <summary>
    /// Determine if the current host is a valid host (local or remote)
    /// </summary>
    /// <returns>True if the current host is permitted to host the game.
</returns>
    public bool IsValidHost()
    {
        if (IsValidLocalHost() == true)
        {
            return true;
        }

        if (IsValidRemoteHost() == true)
        {
            return true;
        }

        return false;
    }

    /// <summary>
    /// Compile a list of hosts in to a fragment of JavaScript.
    /// </summary>
    /// <param name="permittedHosts">List of hosts permitted to host the
game.</param>
    /// <returns>Fragment of JavaScript for testing the current host.
</returns>
    private string CompileHosts(string[] permittedHosts)
    {
        StringBuilder hosts = new StringBuilder();

        for (int i = 0; i < permittedHosts.Length; i++)
        {
            hosts.Append("(document.location.host != '");
            string url = permittedHosts[i];
            if (url.IndexOf("http://") == 0)
            {
                url = url.Substring(7);
            }
            else if (url.IndexOf("https://") == 0)
            {
                url = url.Substring(8);
            }

            hosts.Append(url);
            hosts.Append("')");
            if (i < permittedHosts.Length - 1)
            {
                hosts.Append(" && ");
            }

        }

        return hosts.ToString();
    }

    /// <summary>
    /// Perform a browser check using JavaScript to determine if the current
    /// host is permitted to host the game.
    /// </summary>
    private void CheckWithJavaScript()
    {
        StringBuilder javascriptTest = new StringBuilder();

        javascriptTest.Append("if (");
        // compile test for local hosts
        if (m_permitLocalHost)
        {
            javascriptTest.Append("(document.location.host != 'localhost') && 
(document.location.host != '')");
            if (m_permittedRemoteHosts.Length > 0)
            {
                javascriptTest.Append(" && ");
            }

        }

        // compile test for remote hosts
        javascriptTest.Append(CompileHosts(m_permittedRemoteHosts));
        javascriptTest.Append("){ document.location='");
        javascriptTest.Append(m_bounceToURL);
        javascriptTest.Append("'; }");
        if (Debug.isDebugBuild)
        {
            Debug.Log(javascriptTest);
        }

        Application.ExternalEval(javascriptTest.ToString());
    }

    /// <summary>
    /// Perform a complete check to see if the current host is permitted to
    /// host the game. Bounce the player to the game's home page if it is not.
    /// </summary>
    public void TestPiracy()
    {
        if (Debug.isDebugBuild)
        {
            Debug.Log(String.Format("The absolute URL of the application is
{0}", Application.absoluteURL));
        }

        if (Application.platform != RuntimePlatform.WindowsWebPlayer &&
Application.platform != RuntimePlatform.OSXWebPlayer)
        {
            Debug.Log("Testing for piracy but not in web browser, so not
worrying about it.");
            return;
        }

        // if it's not a valid remote host, bounce the user to the proper URL
        if (IsValidHost() == false)
        {
            if (Debug.isDebugBuild)
            {
                Debug.Log(String.Format("Failed valid remote host test.
Bouncing player to {0}", m_bounceToURL));
            }

            Bounce();
            return;
        }

        // it might appear to be a valid local or remote host, but one final
check in JavaScript to verify that
        CheckWithJavaScript();
    }

}

Be Sociable, Share!

Liked This Post?

Subscribe to the RSS feed or follow me on Twitter to stay up to date!