daikonnbatakeのブログ

【ゲーム】Cyberpunk2077を 30時間程度プレイして感じたことなど

こんにちは。daikonnbatakeです。

 

久しぶりの更新です。

今回はCyberpunk2077 を30時間程度プレイしたので、私なりの感想と考察を記事にしてみたいと思います。

 

私はこのゲームを2018年のE3の時期にトレーラーが発表されたあたりから知っていて、それ以来結構情報を追いながらワクワクして発売を待っていました。

もちろん予約購入して発売日に買ったものの、いろいろあってクソ忙しい生活をしていた(る)のでいまだに30時間くらいしかプレイできていません。

しかし、いろいろ思うところがあったので感想を書いていこうと思います。

 

世界観は大変GOOD! 街をドライブするのが楽しい

サイバーパンクというピンポイントなジャンルを的確に突いているデザインと、どこか荒廃した雰囲気のある街並みを一般人からもぎ取った車で走り抜けるのが堪らなく楽しいゲームです。

ハイキングシミュレーターとして街を堪能するには最高のインタラクティブコンテンツだと思います。

 

正直な感想

①期待度が高すぎた

正直なところを言うと、2019年の頭に大コケをかまして世間を笑いの渦に巻き込んだANTHEMと同じ匂いがするんですよね...

ANTHEMと違って致命的なバグや、ロードがクソ長いとかは無いですが、なんというか世間からの期待度が高すぎた結果、コレジャナイ感が出てしまったというのがあるなーと。

具体的には、街が空っぽに感じてしまうというのが大きな要因かなと思います。

 

当たり前の話ですが、プレイヤーは今作の舞台であるナイトシティにについて一切の知識を持ち合わせていない状態からNewGameするわけです。

その状態でいきなりナイトシティに放り出されて右も左もわからないわけで。

 

何が言いたいのかと言うと、ナイトシティがどういう場所なのか、経済がどう回っているのか、ナイトシティという街の設定が最序盤では全くわからない(いまだに理解できてない)ので存在感が薄っぺらく感じてしまうのです。

 

またチュートリアル終了後、一気に沢山のフラグが立つようで、

街を歩いているだけで1~2分置きに1回は色々な組織の人からご丁寧に自己紹介されたり、サブクエストのお知らせをされます。

結果として、どのような組織がどういう立場でどういう状況に置かれているのか、理解がまったく追い付かなくなるのです。

 

知らない組織からの自己紹介

知らない組織同士の抗争に首を突っ込めと依頼される

何をすればいいのかよくわからない

 

この悪循環でサブクエストが脳死で淡々と作業するだけの物と化してしまっている気がします。

あと純粋に連絡が来る頻度が凄すぎて鬱陶しいと思ってしまった。

 

まあなんと言いますか、ナイトシティのスケールと要素が噛み合っていないというか、プレイヤーのリソースが考慮されていないというか、全体的にちぐはぐな感じがするのです。

私はサイバーパンクというジャンルについて、未来の捉え方が一般的なSFとは一味違い、生々しいリアリティがあるから良いと考えているので、そういう点でサイバーパンクが薄い気がしてしまう点も少し残念です。

 

②細かいバグ(仕様かも?)のせいで没入感が削がれる

①で述べた通りゲームがクラッシュしたり、ロードがクソ長いなどの致命的な不具合こそ無いものの、細かいバグが多数あり

  1. mobキャラが地面に頻繁に埋まっている / 平地でスタックしている
  2. mobキャラの見た目が明らかに50代のオッサンなのに声だけロリ

この2つは特に没入感が削がれます。

1 は 2 に比べてまだマシですがストーリーで盛り上がってるときに見かけるとすごく盛り下がります。

 

2 はストーリー関係なしにすごく盛り下がります。というか脳がフリーズします。

2 についての考察なのですが、これはワンチャンバグじゃない可能性があるんです。

 

どういう事かと言うと、既プレイの人は分かると思いますが、このゲームはキャラクリで体のあんな所やそんなところをいろいろいじれます。

つまり明らかに見た目が女性のキャラを作ったとしても声を男性にできるのです。(もちろん逆もできる)

何が言いたいのかと言うと、ゲームの仕様としてランダムにキャラを生成した結果、見た目がおっさんなのに声がロリという分け分からん現象が起きているのではないか?という話です。

 

これが仕様であると仮定した場合、この仕様が出来た背景を色々考えましたが、恐らくは昨今のゲームにポリコレ狂信者に傾倒する文化があるからではないかと考えます。

特にアメリカで開発されたゲームに多い傾向ですが、ゲームのヒロインがゴリゴリで可愛くないというものがあります。

なぜこうしているのかと言うと、こうしないとポリコレ狂信者にSNSで袋叩きにされるからです。

ポリコレ狂信者は「女性が性的に消費/搾取される存在を助長している!」

などとよくわからないことを連呼して、ただ単にかわいらしいだけのキャラと、それを作った人を批判します。

 

今回の場合、制作サイドが

「体が男性でも何人かに1人は声が女性な人を混ぜないとポリコレ狂信者にシバかれるからそうしよう」

みたいな、そういうふうに思ったのかもしれません。(妄想)

 

でも実際の所、声と見た目が乖離しているとそれに集中が持っていかれてしてしまい、没入感が削がれてしまうんですよね。うーん。

 

バグなら早く治してほしいし、仕様なら考え直してほしいところ。

 

③操作性...

FPSはApex legends しかやった事のない私ではありますが、正直操作性が悪いと思いました。

まあ対戦シューターではないのである程度はしょうがないと思いますが、キーボードマウスでプレイしてもコントローラーでプレイしても、操作性がイマイチなんですよね。

いつの間にか時間が過ぎてる系のゲームって、総じて操作性が極めて洗練されているため、プレイヤーはまるで自分自身がゲーム内で動いているような錯覚に陥る(操作するという事を意識していない)のですが、このゲームはそうではないようです。

8年も開発していたならもう少しどうにかなったのでは?(辛辣)

 

総評

たらたら文句を垂れましたが、まだ言いたいことはいろいろあります。

細かいところを作りこんでいるのに、それらの連携が取れていないせいでガタガタになっているところが非常にもったいない。

ストーリー自体がもっと理解しやすければなぁと(私の頭が悪いのもあるかも)

このゲームで学んだことは

 

ユーザーフレンドリーのためになぜその要素が必要なのかをしっかり考えて、本当に必要なものだけを最高にシンプルにまとめ上げることが必要である

 

ということ。

ストーリーにおいても、ゲームシステムにおいても、要素が多すぎて頭がパンクしがちなんですよね...このゲームは。

作り込みが激しいことは評価すべきだし、実際凄いのですが、その作り込みがかえってユーザーを見放しているようにも見えるのです。

制作サイドが満足するためだけに作られたコンテンツ感が出ちゃっているといいますか...。

極論を言ってしまうと、サイバーパンクな世界を表現するうえでオープンワールドにする必要は無いし、ストーリーに最低限絡むもの以外は廃して良いわけです。

パワーアップ要素についても、このゲームにパワーアップの要素があまり必要に思えなかったりもします。もし私が作るなら武器の種類を増やす程度です。

オープンワールドがなぜ必要なのか、複雑なパワーアップシステムがなぜ必要なのか、プランナーを目指す私は深く考えなければならないなと改めて思いました。

【精進日記】ABC-002

精進した後に復習するためのメモみたいなもんです。
ほぼ自分用に書いてるので読みづらかったらごめんなさい。
特に断りが無い限り回答例は Python で記述します。

A問題

問題の要約

max(X, Y) を出力せよ。

回答例

print(max(map(int,input().split())))

ポイント

特にありません。

B問題

問題の要約

文字列 W から すべての a, i, u, e, o を消去して出力せよ。

回答例

print(''.join([i for i in list(input()) if i not in list('aiueo')]))

ポイント

特にありません。

C問題

問題の要約

二次元平面上の座標が 3 組与えられるので、各頂点を結んで出来る三角形の面積を求めよ。

回答例

x,y,a,b,c,d = list(map(int,input().split()))
print(abs((a-x)*(d-y) - (b-y)*(c-x))/2)

ポイント

特にありません。

D問題

問題の要約

N 個の頂点と M 個の辺が与えられる。
一部の頂点のすべてが互いに辺でつながっている状態を「派閥」と呼ぶ場合、派閥の中で一番大きなものの頂点の数を求めよ。

回答例

N, M=map(int, input().split())

ans = 0
v = [set([i])for i in range(N)]

for i in range(M):
    x, y=map(int, input().split())
    x-=1; y-=1
    v[x].add(y)
    v[y].add(x)

for i in range(1,1<<N):
    s = set()
    m = 0
    for j in range(N):
        if i & 1<<j:
            s.add(j)
    for j in s:
        if s & v[j] == s:
            m += 1
    ans = max(ans, m)
print(ans)

ポイント

「全ての頂点が互いに辺でつながっている状態」は、bit全探索で部分集合を求め、それと同じ部分集合を持つ集合を全探索すれば求めることができる。

【精進日記】ABC-001

精進した後に復習するためのメモみたいなもんです。
ほぼ自分用に書いてるので読みづらかったらごめんなさい。
特に断りが無い限り回答例は Python で記述します。

A問題

問題の要約

H1とH2 の差を求めよ。

回答例

print(int(input())-int(input()))

ポイント

特にありません。

B問題

問題の要約

  • m<100 の場合 → VV = 00
  • 100 ≦ m ≦ 5000 の場合 → VV = m / 100 if (9 < m / 100) else '0' + str(m / 100)
  • 6000 ≦ m ≦ 30000 の場合 → VV = m / 1000 + 50
  • 35000 ≦ m ≦ 70000 の場合 → VV = (m / 1000 - 30) / 5 + 80
  • 70000 < m の場合 → VV = 89

入力 m から VV を求めよ。
なお、答えが整数にならない入力や、5000 < m < 6000 のような入力は与えられない。

回答例

m = int(input())

if m < 100: a = '00'
elif 100 <= m <= 5000: a = m//100 if (9<m//100) else '0'+str(m//100)
elif 6000 <= m <= 30000: a = m//1000 + 50
elif 35000 <= m <= 70000: a = (m//1000-30)//5+80
else: a = 89

print(a)

ポイント

このような複雑な条件分岐がある問題は、条件を一度紙などに書き出して整理してみましょう。

C問題

問題の要約

  1. 風向きの角度を10倍した値 Deg から 16 方位を求めよ
  2. 60秒あたりに風車が回った距離 Dis から 風速を求め、風速から風力を求めよ

回答例

from decimal import Decimal as d
Deg, Dis = map(int, input().split())
a = 'N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW N'.split()
b = [2, 15, 33, 54, 79, 107, 138, 171, 207, 244, 284, 326, 2000]

x = a[(Deg*10 + 1125) // 2250]
y = 0

for i in range(13):
    if  (d(str(Dis))/d('6.0')).quantize(0, rounding='ROUND_HALF_UP') <= b[i]:
        y = i
        break

print(x if y else 'C', y)

ポイント

  • 場合分けをリストで管理しましょう。
  • 角度に注意してください。N (北) の範囲は 348.75 ≦ r < 360.0 or 0 ≦ r < 11.25 を満たす r の範囲を指します。
  • 小数の誤差に注意しましょう。Python では Decimal モジュールを利用することで正確な計算 / 丸めを行う事ができます。

D問題

問題の要約

  1. 時刻を5分刻みに変換せよ
  2. 降り始め/降り終わり をいもす法でシミュレーションし、出力せよ

回答例

N = int(input())

a = [0]*290

for i in range(N):

    S, E = input().split('-')
    S = int(S[:2])*12 + (int(S[-2:])//5)
    E = int(E[:2])*12 + (1 if int(E[-2:]) % 5 else 0) + int(E[-2:])//5

    a[S + 1] += 1
    a[E + 1] -= 1

s, e = '0000', '0000'
rain = False

for i in range(1,290):

    a[i] = a[i - 1]+a[i]

    h, m, = str((i-1)//12), str((i - 1)%12*5)
    h = h if 1 < len(h) else '0' + h
    m = m if 1 < len(m) else '0' + m

    if rain != (0 < a[i]):
        if rain:
            e = h + m
            print(s + '-' + e)

        else:
            s = h + m

    rain = 0 < a[i]

ポイント

この問題は累積和の応用みたいな問題です。
「5分刻み」に時間を変更するには、以下の式を用います。

# n = 問題の制約に従う時間を表す4桁の整数 , h = 時間 , m = 分
h = n // 12
m = n % 12

これで、0000 ~ 2400 を 0 から 288 に変換する事ができます。
復元するときはこの逆をやればいいです。

あとは 長さ290 の配列を用意して(0も範囲に含むので+1、いもす法を行うための余白を追加するために +1 となり、 288+2 で 290 個の要素が必要です)シミュレーションすることで解く事ができます。

自己紹介など(?)

こんにちは。daikonnbatake および daikonn および かがまる として活動している「daikonnbatake」と申します。

お前何者や?

ゲームプランナー志望の専門学校生(2020年4月入学)です。

いわゆる意識高い系みたいな、周りにイキリ散らかして嫌われるタイプの人で、

  • プログラミング
  • イラスト
  • 3DCG関連全般
  • 作曲(ちょっとだけ)

など、幅広く浅くやってます。

プログラミングだけは少し自信がある (2020年10月現在 AtCoder 茶) ので、このブログもそういう方面が多くなるかも。

ブログの方針

特になし。

強いて言うなら、学校のとある授業で「論理的説明力を鍛えるためにブログ書きます!!」と言ってしまったので後に引けなくなったなど。

一応過去に技術ブログをちょっとやっていて、1000円くらい収益を出したくらいでやめましたね・・・

まあ雑記だし、利益とか考えてません。

収益化考えだすから自鯖とかイキって立てて採算取れなくなるんですよ(自戒)

カテゴリーは分けるけど、

  • ゲームのレビュー
  • 気になる時事ネタ
  • 技術的な話
  • イラストの話
  • 個人的な話(部活の面白かったこととか?)

を中心に書いていくつもりではあります。

面白がって好んで見るべきブログにはなり得ないかと思いますがよろしくおねがいいたします。