the cutting room mirror

Sonic Unleashed (Wii, PlayStation 2)

This article has a talk page!
view on tcrf.net
SOMETIMES I SEE A TEXT BOX AND I JUST CAN'T HELP MYSSDFGFFDHFGDJGGFSHGDFH

This page sucks.
If you could make it suck less, that would be awesome.
Specifically: Several things are just lazily plagiarized from the Sonic Fandom wiki. Clean this up and give proper credit.

To do:
There's apparently a model of the Tornado-1 (which, in this version, only appears in cutscenes) in the files.

The Wii and PlayStation 2 versions of Sonic Unleashed share the same story and gameplay concepts as their Xbox 360 and PlayStation 3 counterparts, but they feature different level designs, a mission-based structure for progression, and a point-and-click format for hubs. They also have fewer levels, with Empire City being completely absent.

The PS2 version was the last Sonic game released for the system. Interestingly, the PS2 version was never released in Japan, though the North American version has a Japanese language option.

Unused Graphics#

Tokyo Game Show Leftovers#

Graphics leftover from the 2008 Tokyo Game Show build can be found in the TGS folder.

Sun and Moon Medals#

Early

Final

KeyMain.onz contains early graphics for the Sun/Moon Medals, depicting vastly different designs compared to those in the final game.

Early Rank HUD#

Early

Final

The Cockpit folder shows that the ranking system originally used medals for completing stages, similar to Sonic and the Secret Rings. The final game uses letter grades, as in the 360 and PS3 versions.

Apotos Night#

SonicUnleashedNigjt.png

An unused night version of the Apotos level hub. You can only see this area at daytime in-game.

Spagonia Quick Time Event Enemy#

SonicUnleashedNpc enemy wait.png

A sprite of a Gaia Nightmare that was meant to be used in the Spagonia QTE cutscene.

Test NPCs#

1_npc_tes01

2_npc_tes02

4_npc_tes04

Unused character renders of Denise and Labib for testing purposes. Interestingly, while Denise does appear in this version, Labib does not.

Test NPC Dialogue#

2_fte_FileName_000

3_fte_FileName_001

A test font for the NPC dialogue.

(Source: Sonic Wiki Zone, original TCRF research)

Unused Models#

Debug Primitive#

debug_primitive.onz contains several basic geometric shaped models that are meant to be used purely for debugging purposes. These models can also be found in Shadow the Hedgehog, Sonic and the Secret Rings, and Sonic and the Black Knight.

NPCs#

The load_etc folder contains models of various NPCs, all from Shamar with the exception of Lilli. The Wii and PS2 versions use pre-rendered sprites to represent NPCs in villages; it's unknown if the villages were originally meant to be 3D hub worlds. A duplicate Labib model for testing also exists. Oddly, Lilli's model is labeled yman, meaning "young man".

1-UP Capsule#

0_itembox_1up is an early version of the 1-UP capsule with the same icon as the one from Sonic the Hedgehog (2006). Collecting it has no effect. The final game's 1-UP capsule uses the silhouette of Sonic's head from the Sonic Team logo, with a blue border instead of a yellow one.

Although it's not seen normally, this capsule is present out of bounds in the second Windmill Isle nighttime tutorial, "Use those arms to get acrobatic!", placed where a secret item container exists in the main level. In the final game, 1-UP capsules can only be found in Gaia Gates, so its presence here suggests that they were once present in regular stages.

Internal Level Structure#

Day Stages

Night Stages

Watch on YouTube

Watch on YouTube

Avid fans of the Wii and PS2 versions already know that there are more night stages than day stages. However, filenames and folders reveals that this wasn't always the case. Every single day stage has two acts internally, with Rooftop Run and Dragon Road even having three acts, however the second and third acts are always reserved for extra missions, which load certain areas needed. Additionally, each night stage is a single act for that location, just different areas. This suggests that at some point, each location would've been given two day acts and one night act, before they were split up. While there are second acts for all night stages, they are instead used for missions.

The night acts appear to have been split apart early on, as Windmill Isle and Rooftop Run have little evidence left of being a single long stage, although later stages are much more obviously split apart, often having the geometry of the next area visible from the end of the stage. None of them have triggers to load the next area, however. The day acts, on the other hand, were likely split apart due to time constraints or hardware limitations, as some of the later stages use similar flat collision templates.

Unused Sounds#

Chip#

The BRSAR file contains various unused voice lines from Chip, many of them being intended to teach the player about the mechanics or a stage.

Wii-Specific#

String Name

Audio

Transcript

V_026

"Press the Y Button button to tackle an enemy."

V_027 & V_029

"Press the X Button button to tackle an enemy."

V_030

"Press the A Button button to tackle an enemy."

V_040

"Once it's full, press the X Button button to do a sonic boost."

V_041

"Once it's full, press the A Button button to do a sonic boost."

V_095

"If you press the Z button in mid-jump, you can stomp on bad guys!"

V_109

"Hold down the Z button and tap left or right on control stick to do a quick step."

V_125

"Press the X Button button when you see a line of rings to do a light speed dash."

V_126

"Press the A Button button when you see a line of rings to do a light speed dash."

V_152

"Swing the Wii Remote and Nunchuck at the same time to do your special attack."

V_153

"Press the A button to do your special attack."

V_154

"Press the L button and R button at the same time to do your special attack."

V_133

"When the gauge is full, press the X button or the Y button for the super sonic boost!"

PS2-Specific#

String Name

Audio

Transcript

V_023

"Press the circle button to tackle an enemy."

V_024

"Press the triangle button to tackle an enemy."

V_038

"Once it's full, press the triangle button button to do a sonic boost."

V_122

"Press the triangle button button when you see a line of rings to do a light speed dash."

V_091

"Once the Unleashed Gauge is full, press the L1 Button or the L2 Button."

V_155

"Press the triangle button button to do your special attack."

Other#

String Name

Audio

Transcript

V_011

"Looks like collecting rings gives you energy back, Sonic!"

V_012

"This jumbled up ball of energy feels…it feels just like your power, Sonic!"

V_065

"Once you grabbed it, you can throw it! And that goes for enemies too!"

V_072

"Hey, what's this? We should take it with us and check it out later."

V_073

"Hey look! It's another one of those things, Sonic! Let's keep looking for more!"

V_075

"We're up to three now! Wonder what happens when you gather three?"

V_100

"Weird, somebody left a bobsled out here. Hey, let's go for a ride, Sonic."

V_101

"We've gotta get up that tower, Sonic! That's the only way forward."

V_102

"Hmm... That thing looks like a lever, maybe we can move it."

V_118

"Get up enough speed, and you can run right across water. Slow down and you'll sink though, so be careful."

V_119

"That spray looks awful cold, Sonic. If you get hit with that, you'll freeze."

V_084

"That new move you learned sounds awesome! Let me see it, Sonic."

V_085

"Sounds like the new move you've picked up sounds does something special, Sonic. Let's try it out."

V_086

"C'mon! Let's see that move already, Sonic!"

V_087

"Show me that new move, Sonic! I wonder what it does?"

Werehog#

String Name

Audio

Transcript

V_030

"Oh yeah, that's right baby!"

V_031

"No way!"

V_039

"Oh no!"

V_040

"Darn, I blew it!"

V_041

"Amazing!"

V_069

"Strike three, monster! That's enough out of you!"

V_072

"Sorry, I'm in a rush here!"

V_075

"I know little girls who are better with a hammer than you... Well, one anyway."

V_082

"Game over, Eggman! Looks like I win!"

Many of the Werehog's lines from 360 and PS3 versions, such as defeating a boss or earning a certain ranking when completing a stage, are unused here.

Debug Menu Strings#

Sonic Action
Sample Action
Attract
Option
Movie
Focus Title
Evil Result3
ItemGet
Scenario
Credit
SaveMain
Gallery_Top
Sonic Motion Viewer
Model Viewer
Havok Test
Screen Change
MemoryCard Test
Make Mode

Present in the PS2 version's executable at 0x684948 is text for a debug menu.

Internal Location Names#

CGameSetting::CNutsMission
MYKONOS
TUNDRA
EU
CHINA
PETRA
BEACH
EGGMANLAND

Present at 66A0D8 in the main executable is some debug text, including the internal names used for locations that Sonic visits.

Test NUT Files#

Within the "Adventure" folder, there's a few ".nut" files that were meant for testing various things during development, ranging from NPCs to Chip himself.

test_chip_talk.nut
// テスト/チップ会話

one_this_ <- ::allone_.at( "load_etc/adventure.one" );

// 外部スクリプトのインポート
SquirrelPlus.Run(one_this_.at( "free_cursor.nut" ), "data/etc/adventure/free_cursor.nut" );
SquirrelPlus.Run(one_this_.at( "talk.nut" ), "data/etc/adventure/talk.nut" );

language_ <- ::ModeSwitch.Instance().GetLanguage();
Language_ <- "Japanese";

sonic_evil_scene_prefix_ <- "so"; // "so" "ev"

env_ <- this;




//============================================================================
// 本体 
//============================================================================


// クラス
class CTestChipTalk
{
    constructor()
    {
        ///
    }
    
    talk_filename_ =    "load_etc/talk_Chip00.one";         // 会話
    text_filename_ =    "load_etc/cnv_Chip00_cnv.one";      // テキスト
    base_filename_ =    "load_etc/csd_cp_info_window.one";  // 基本
    chip_filename_ =    "load_etc/model_chip.one";          // チップ
    
    chip_talk_ = TChipTalk();
};


// メイン
function CTestChipTalk::Main()
{
    // データロード
    ::allone_.at( talk_filename_ );
    ::allone_.at( text_filename_ );
    ::allone_.at( base_filename_ );
    ::allone_.at( chip_filename_ );
    
    // データロード待ち
    while( !::allone_.isLoad() ) ::suspend();

    // 会話データはNUTで設定
    local talk_one = ::allone_.at(talk_filename_);          // 会話データ(ONE)
    local talk_nut = delegate ::env_ : {};                  //
    SquirrelPlus.Run( talk_one.at(0), "none", talk_nut );   // 会話データ(NUT)
        
    // データ設定
    chip_talk_.SetTalkData( talk_nut );
    chip_talk_.SetTextData( ::allone_.at(text_filename_) );
    chip_talk_.SetBaseData( ::allone_.at(base_filename_) );
    chip_talk_.SetChipData( ::allone_.at(chip_filename_) );
    
    chip_talk_.Start( "ct_SG_00_CP_00" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_10_CP_00" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_10_CP_01" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_10_CP_02" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_10_CP_03" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_20_CP_00" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_20_CP_01" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_20_CP_02" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_30_CP_00" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    chip_talk_.Start( "ct_SG_40_CP_00" );
    while( !chip_talk_.CheckEnd() ) ::suspend();
    
    // データ解放
    ::allone_.erase( talk_filename_ );
    ::allone_.erase( text_filename_ );
    ::allone_.erase( base_filename_ );
    ::allone_.erase( chip_filename_ );
}


// コンテクストの異なるオブジェクトの毎処理
function CTestChipTalk::Update()
{
    ///
}


// 描画
function CTestChipTalk::Render()
{
    chip_talk_.Render();
}




//============================================================================
// 呼び出し 
//============================================================================


// 初期化
function Construct()
{
    runclass_ <- CTestChipTalk();   
    thread_func_ <- function(e)
    {
        e.runclass_.Main();
    }   
    thread_ <- ::newthread(thread_func_);
    thread_.call(this);
}


// 毎時実行ハンドリング関数
function Update()
{
    if (!("thread_" in this))
    {
        Construct();
    }
    if (thread_.getstatus() == "suspended")
    {
        thread_.wakeup();
        runclass_.Update();
    }
    return thread_.getstatus();
}


// 実行ステータスを返す
function GetStatus()
{
    if (!("thread_" in this)) return null;
    return thread_.getstatus();
}


// 描画ハンドリング関数
function Render()
{
    runclass_.Render();
}
test.nut
//============================================================================
// 基本
//============================================================================


// クラス
class Test extends TChipTalk 
{
    // コンストラクタ
    constructor()
    {
        Test_ = {
            
            xxx_ = 0,
            
            chip_talk_ = TChipTalk(),
            
            npc_model_ = [ TNPCModel(), TNPCModel() ],
        };
    }
    
    Test_ = null;
    
    npc_talk_ = null
};


// メイン
function Test::Main()
{
    // NPC会話
    if( 1 )
    {
        local nut = one_this_.at( "npc_talk.nut" );
        npc_talk_ = delegate ::env_ : {};
        SquirrelPlus.Run( nut, "data/etc/adventure/npc_talk.nut", npc_talk_ );

        npc_talk_.Construct( 0, "africa", "day", "area_A" );
        while( npc_talk_.GetStatus() == "suspended" ) ::suspend();

        npc_talk_.Construct( 0, "africa", "day", "area_B" );
        while( npc_talk_.GetStatus() == "suspended" ) ::suspend();

        npc_talk_.Construct( 0, "africa", "day", "area_C" );
        while( npc_talk_.GetStatus() == "suspended" ) ::suspend();

        npc_talk_  = null;
    }
    
    // チップ会話
    if( 0 )
    {
        // データロード
        ::allone_.at( "load_etc/cnv_Chip00_Japanese.one" ); // テキストデータ
        ::allone_.at( "load_etc/talk_Chip00.one" );         // 会話データ
        ::allone_.at( "load_etc/csd_ui_capital_talk.one" ); // 黒枠データ
        ::allone_.at( "load_etc/csd_cp_info_window.one" );  // 吹き出しデータ
        while( !::allone_.isLoad() ) ::suspend();           // ロード待ち

        // データ取得
        local text_one = ::allone_.at( "load_etc/cnv_Chip00_Japanese.one" );        // テキストデータ
        local talk_one = ::allone_.at( "load_etc/talk_Chip00.one" );                // 会話データ(ONE)
        local blackframe_one = ::allone_.at( "load_etc/csd_ui_capital_talk.one" );  // 黒枠データ
        local balloon_one = ::allone_.at( "load_etc/csd_cp_info_window.one" );      // 吹き出しデータ

        local talk_nut = delegate ::env_ : {};                                      //
        SquirrelPlus.Run( talk_one.at(0), "none", talk_nut );                       // 会話データ(NUT)
        
        // データ設定
        Test_.chip_talk_.SetTextData( text_one );
        Test_.chip_talk_.SetTalkData( talk_nut );
        Test_.chip_talk_.SetBlackFrameData( blackframe_one );
        Test_.chip_talk_.SetBalloonData( balloon_one );
        
        
        // 会話1
        Test_.chip_talk_.Start( "ct_SG_01_CP_03" );     
        while( Test_.chip_talk_.CheckEnd()==false ) ::suspend();

        // 会話2
        Test_.chip_talk_.Start( "ct_SG_01_CP_05" );     
        while( Test_.chip_talk_.CheckEnd()==false ) ::suspend();
        
        // 会話1
        Test_.chip_talk_.Start( "ct_SG_01_CP_10" );     
        while( Test_.chip_talk_.CheckEnd()==false ) ::suspend();

        // 会話1
        Test_.chip_talk_.Start( "ct_SG_01_CP_11" );     
        while( Test_.chip_talk_.CheckEnd()==false ) ::suspend();

        // 会話2
        Test_.chip_talk_.Start( "ct_SG_01_CP_12" );     
        while( Test_.chip_talk_.CheckEnd()==false ) ::suspend();
        
        // 会話1
        Test_.chip_talk_.Start( "ct_SG_01_CP_13" );     
        while( Test_.chip_talk_.CheckEnd()==false ) ::suspend();

        
        // データ解放
        ::allone_.erase( "load_etc/cnv_Chip00_Japanese.one" );  // テキストデータ
        ::allone_.erase( "load_etc/talk_Chip00.one" );          // 会話データ
        ::allone_.erase( "load_etc/csd_ui_capital_talk.one" );  // 黒枠データ
        ::allone_.erase( "load_etc/csd_cp_info_window.one" );   // 吹き出しデータ
    }

    // NPCモデル
    if( 0 )
    {
        // データロード
        ::allone_.at( "load_etc/npc_test01.one" );
        ::allone_.at( "load_etc/npc_test02.one" );
        while( !::allone_.isLoad() ) ::suspend();   // ロード待ち

        // データ取得
        local one01 = ::allone_.at( "load_etc/npc_test01.one" );
        local one02 = ::allone_.at( "load_etc/npc_test02.one" );

        // データ設定
        Test_.npc_model_[0].SetTextureData( one01 );
        Test_.npc_model_[1].SetTextureData( one02 );
        
        // 設定(L)
        Test_.npc_model_[0].SetPosition( CVector( -128.0, 0.0, 0.0 ) );
        Test_.npc_model_[0].SetDraw( 0 );
        
        // 設定(R)
        Test_.npc_model_[1].SetPosition( CVector( 128.0+128.0, 0.0, 0.0 ) );
        Test_.npc_model_[1].SetReverse( 1 );

        while(1) ::suspend();
    }
};


// 更新
function Test::Update()
{
    ///
    
    if( npc_talk_!=null ) npc_talk_.Update();
}


// 描画
function Test::Render()
{
    Test_.chip_talk_.Render();

    if( npc_talk_!=null ) npc_talk_.Render();
}




//============================================================================
// 呼び出し
//============================================================================


// 初期化
function Construct()
{
    // 実行クラスを設定
    runclass_ <- Test();
    
    // スレッド関数の作成
    thread_func_ <- function(env)
    {
        // 実行クラスのメイン
        env.runclass_.Main();
    }
    
    // スレッドを作成
    thread_ <- ::newthread(thread_func_);
    
    // スレッドの開始
    thread_.call( this );
}


// 更新
function Update()
{
    // スレッドチェック
    if( !("thread_" in this) ) return null;
    
    // スレッドが停止中の場合は再開
    if( thread_.getstatus() == "suspended" )
    {
        // スレッドの再開
        thread_.wakeup();
        
        // 実行クラスの更新
        runclass_.Update();
    }
    
    // スレッドのステータス取得
    return thread_.getstatus();
}


// ステータス取得
function GetStatus()
{
    // スレッドチェック
    if( !("thread_" in this) ) return null;
    
    // スレッドのステータス取得
    return thread_.getstatus();
}


// 描画
function Render()
{
    // スレッドチェック
    if( !("thread_" in this) ) return;
    
    // 実行クラスの描画
    runclass_.Render();
}
test_npc_talk.nut

// テスト/NPC会話




one_this_ <- ::allone_.at( "load_etc/adventure.one" );

// 外部スクリプトのインポート
SquirrelPlus.Run(one_this_.at( "free_cursor.nut" ), "data/etc/adventure/free_cursor.nut" );
SquirrelPlus.Run(one_this_.at( "talk.nut" ), "data/etc/adventure/talk.nut" );

language_ <- ::ModeSwitch.Instance().GetLanguage();
Language_ <- "Japanese";

sonic_evil_scene_prefix_ <- "so"; // "so" "ev"

env_ <- this;
free_cursor_ <- null;




//============================================================================
// 本体 
//============================================================================


// クラス
class CTextNPCTalk
{
    constructor()
    {
        ///
    }
    
    child_ = null;
};


// メイン
function CTextNPCTalk::Main()
{
    ::free_cursor_ = CFreeCursor();

//---

    Talk( 9999, "eu", "day", "ev_SG_06_cp_01" );


//  NPCTalk( 860, "beach", "night", "a" );
/*
    NPCTalk( 860, "beach", "night", "a" );
    NPCTalk( 860, "beach", "night", "b" );
    NPCTalk( 860, "beach", "night", "c" );
    NPCTalk( 860, "beach", "night", "d" );

    NPCTalk( 1030, "mykonos", "day", "a" );
    NPCTalk( 1030, "mykonos", "day", "b" );
    NPCTalk( 1030, "mykonos", "day", "c" );
    NPCTalk( 1030, "mykonos", "day", "d" );
*/
/*
    NPCTalk( 0, "test", "day", "a" );
    NPCTalk( 0, "test", "day", "b" );
    NPCTalk( 0, "test", "day", "c" );
    NPCTalk( 0, "test", "day", "d" );
    NPCTalk( 0, "test", "day", "e" );
    NPCTalk( 0, "test", "day", "f" );
    NPCTalk( 0, "test", "day", "g" );
    NPCTalk( 0, "test", "day", "h" );
    NPCTalk( 0, "test", "day", "i" );
    NPCTalk( 0, "test", "day", "j" );
    NPCTalk( 0, "test", "day", "k" );
    NPCTalk( 0, "test", "day", "l" );
*/
}


function CTextNPCTalk::Talk( scene, capital, time, GroupID )
{
    local nut = one_this_.at( "npc_talk.nut" );
    child_ = delegate ::env_ : {};
    SquirrelPlus.Run( nut, "data/etc/adventure/npc_talk.nut", child_ );

    child_.Construct( scene, capital, time, GroupID );
    while( child_.GetStatus() == "suspended" ) ::suspend();
    child_  = null;
}


function CTextNPCTalk::NPCTalk( scene, capital, time, area )
{
    local nut = one_this_.at( "npc_talk.nut" );
    child_ = delegate ::env_ : {};
    SquirrelPlus.Run( nut, "data/etc/adventure/npc_talk.nut", child_ );

    child_.ConstructNPC( scene, capital, time, area );
    while( child_.GetStatus() == "suspended" ) ::suspend();
    child_  = null;
}


// コンテクストの異なるオブジェクトの毎処理
function CTextNPCTalk::Update()
{
    if (child_ != null) child_.Update();
    if (free_cursor_ != null) free_cursor_.Update();
}


// 描画
function CTextNPCTalk::Render()
{
    if (child_ != null) child_.Render();
    if (free_cursor_ != null) free_cursor_.Render();
}




//============================================================================
// 呼び出し 
//============================================================================


// 初期化
function Construct()
{
    runclass_ <- CTextNPCTalk();    
    thread_func_ <- function(e)
    {
        e.runclass_.Main();
    }   
    thread_ <- ::newthread(thread_func_);
    thread_.call(this);
}


// 毎時実行ハンドリング関数
function Update()
{
    if (!("thread_" in this))
    {
        Construct();
    }
    if (thread_.getstatus() == "suspended")
    {
        thread_.wakeup();
        runclass_.Update();
    }
    return thread_.getstatus();
}


// 実行ステータスを返す
function GetStatus()
{
    if (!("thread_" in this)) return null;
    return thread_.getstatus();
}


// 描画ハンドリング関数
function Render()
{
    runclass_.Render();
}
test_talk_qte.nut
// テスト/会話画面QTE




one_this_ <- ::allone_.at( "load_etc/adventure.one" );

// 外部スクリプトのインポート
SquirrelPlus.Run(one_this_.at( "free_cursor.nut" ), "data/etc/adventure/free_cursor.nut" );
SquirrelPlus.Run(one_this_.at( "talk.nut" ), "data/etc/adventure/talk.nut" );

language_ <- ::ModeSwitch.Instance().GetLanguage();
Language_ <- "Japanese";

sonic_evil_scene_prefix_ <- "so"; // "so" "ev"

env_ <- this;




//============================================================================
// 本体 
//============================================================================


// クラス
class CTestTalkQTE
{
    constructor()
    {
        ///
    }
    
    child_ = null;
};


// メイン
function CTestTalkQTE::Main()
{
    local nut = one_this_.at( "talk_qte.nut" );
    child_ = delegate ::env_ : {};
    SquirrelPlus.Run( nut, "data/etc/adventure/talk_qte.nut", child_ );

    child_.Construct();
    while( child_.GetStatus() == "suspended" ) ::suspend();
    child_  = null;
}


// コンテクストの異なるオブジェクトの毎処理
function CTestTalkQTE::Update()
{
    if (child_ != null) child_.Update();
}


// 描画
function CTestTalkQTE::Render()
{
    if (child_ != null) child_.Render();
}




//============================================================================
// 呼び出し 
//============================================================================


// 初期化
function Construct()
{
    runclass_ <- CTestTalkQTE();    
    thread_func_ <- function(e)
    {
        e.runclass_.Main();
    }   
    thread_ <- ::newthread(thread_func_);
    thread_.call(this);
}


// 毎時実行ハンドリング関数
function Update()
{
    if (!("thread_" in this))
    {
        Construct();
    }
    if (thread_.getstatus() == "suspended")
    {
        thread_.wakeup();
        runclass_.Update();
    }
    return thread_.getstatus();
}


// 実行ステータスを返す
function GetStatus()
{
    if (!("thread_" in this)) return null;
    return thread_.getstatus();
}


// 描画ハンドリング関数
function Render()
{
    runclass_.Render();
}

NPC Talk Test#

    [area_A]
        [no_00]
            ※キャラ
    [area_B]
        [no_00]
            待機
        [no_01]
            話す
    [area_C]
        [no_00]
            通常時の位置(1F)
        [no_01]
            小刻みに揺れる(4F)
        [no_02]
            拡大縮小でびっくりしてるように見せる(4フレーム)
        [no_03]
            左に消える(5フレーム)
        [no_04]
            左から出現(5フレーム)
        [no_05]
            下に消える(20フレーム)
        [no_06]
            下から出現(20フレーム)
        [no_07]
            アルファで消える(10フレーム)
        [no_08]
            アルファで出現(10フレーム)
    [area_D]
        [no_00]
            左の人が喋ります
        [no_01]
            右の人が喋ります
    [area_E]
        [no_00]
            速く喋ります
        [no_01]
            普通に喋ります
        [no_02]
            遅く喋ります
    [area_F]
        [no_00]
            一郎(1)
        [no_01]
            一郎(2)
        [no_02]
            一郎(3)
        [no_03]
            二郎(1)
        [no_04]
            二郎(2)
        [no_05]
            二郎(3)
        [no_06]
            三郎(1)
        [no_07]
            三郎(2)
        [no_08]
            三郎(3)
    [area_G]
        [no_00]
            ※背景
    [area_H]
        [no_00]
            白くなる
        [no_01]
            白から戻る
        [no_02]
            黒くなる
        [no_03]
            黒から戻る
    [area_I]
        [no_00]
            SND_SE_SYSTEM_01_SYS_COUNT3
        [no_01]
            SND_SE_SYSTEM_02_SYS_COUNT2
        [no_02]
            SND_SE_SYSTEM_03_SYS_COUNT1
        [no_03]
            SND_SE_SYSTEM_04_SYS_COUNT_GO
    [area_J]
        [no_00]
            BGM_Son_Stg_Myk
        [no_01]
            BGM_Son_Stg_Snw
        [no_02]
            BGM_Son_Stg_Euc
        [no_03]
            BGM_Son_Stg_Chn
        [no_04]
            BGM_Son_Stg_Ptr
        [no_05]
            BGM_Son_Stg_Sea
        [no_06]
            BGM_Son_Stg_Egb1
        [no_07]
            BGM_Son_Stg_Egb2
    [area_K]
        [no_00]
            あいうえお
            かぎくけこ
            さしすせそ
            たちつてと
        [no_01]
            あいうえお
            かぎくけこ
            さしすせそ
            たちつてと
        [no_02]
            あいうえお
            かぎくけこ
            さしすせそ
            たちつてと
        [no_03]
            あいうえお
            かぎくけこ
            さしすせそ
            たちつてと
    [area_L]
        [no_00]
            質問?
    [area_L_1]
        [no_01_1]
            回答A
        [no_02_1]
            リアクションA
    [area_L_2]
        [no_01_2]
            回答B
        [no_02_2]
            リアクションB
    [label]
        [Ichiro]
            イチロー
        [Jiro]
            ジロー
        [Saburo]
            サブロー

The test NPCs have dialogue, found inside of "npctalk_talk_Test_Day_0.onz".

Oddities#

The tree textures for Dark Gaia's running sections use the prefix nyc. In the Xbox 360 and PlayStation 3 versions, the trees are reused from Empire City, which is internally referred to as NYCity; however, Empire City is absent in this version. There's no discrepancy in the internal stage numbering, so it's unlikely this is an indication of Empire City being in the Wii version at some point.

Version Differences#

To do:
Get images of the different versions, and investigate both versions for any differences.

Regional Differences#

Like the 360 and PS3 versions, the game is titled Sonic World Adventure in Japan, which was actually the working title of the game, back when it was developed as the third Adventure game, before the decision was made to rename it for international markets due to the stark change in gameplay.

Platform Differences#

This version of Sonic Unleashed was first developed for the Wii before being ported to the PS2.

  • The Options menu has some differences across the two versions:

Wii

PS2

SonicUnleashedWii RumbleSettingsTexture.png

:* The haptic feedback settings are referred to as Rumble Settings in the Wii version and Vibration Settings in the PS2 version. The Vibration Settings menu graphic does exist in the Wii version, but goes unused.

:* The Wii version includes a Controller Settings option to toggle between button prompts for the Wii Remote and Nunchuk, GameCube controller, and Classic Controller.

  • The Wii version includes support for anamorphic widescreen, which is missing in the PS2 version.
  • Visuals have been pared back on PS2, with lower-resolution textures and materials throughout the game.
  • Character models are less detailed in the PS2 version. For example, Sonic's spines are not rigged, resulting them being completely static.
  • The PS2 version's load times are longer.